Skip to content

Commit

Permalink
Merge pull request #226 from Phuire-Research/Consistency
Browse files Browse the repository at this point in the history
True Consistency Update v0.1.72
  • Loading branch information
REllEK-IO committed May 17, 2024
2 parents 3a70432 + f6d1102 commit 1c0666a
Show file tree
Hide file tree
Showing 8 changed files with 181 additions and 42 deletions.
41 changes: 21 additions & 20 deletions Axium.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,31 +112,32 @@ export type AxiumState = {
## Axium Qualities for Internal Use
Please avoid using these qualities, but are providing explanations to understand the inner workings of the axium.
* addConceptsFromQue - This will be ran from the internal axium principle and take all concepts added to said que to include within the axium and increment the current generation.
* appendActionListToDialog - Takes the final output of a strategy and appends such into a Stratimux dialog if storeDialog is set to True.
* badAction - If logging is set to true, this will log any BadAction via its payload of the invalidated action that is created from the primeAction() helper function.
* conclude - This is a pure action that has no reducer or method. And will only be issued upon the conclusion of an ActionStrategy. If ownership is part of the concept load. This allows for the conclude to clear the final action's locks via its OwnershipLedger Entries.
* initializePrinciples - Is a delayed action to allow for the internal set up of the axium at run time.
* open - Similar to conclude, notifies principles when the axium is open to their emissions. Part of the initialization, addConcept, and removeConcept strategies.
* close - This will will cancel all internal subscriptions that the axium has access to. As well as all Steams will be completed. The external close() function that the createAxium supplies, dispatches this action. Or can be ran specially via an internal principle towards its governing axium or that of another axium that it is subscribed to.
* removeConceptsViaQue - This will run via the internal axium principle. Whenever there is an addition to this remove que.
* axiumAddConceptsFromQue - This will be ran from the internal axium principle and take all concepts added to said que to include within the axium and increment the current generation.
* axiumAppendActionListToDialog - Takes the final output of a strategy and appends such into a Stratimux dialog if storeDialog is set to True.
* axiumBadAction - If logging is set to true, this will log any BadAction via its payload of the invalidated action that is created from the primeAction() helper function.
* axiumConclude - This is a pure action that has no reducer or method. And will only be issued upon the conclusion of an ActionStrategy. If ownership is part of the concept load. This allows for the conclude to clear the final action's locks via its OwnershipLedger Entries.
* axiumInitializePrinciples - Is a delayed action to allow for the internal set up of the axium at run time.
* axiumOpen - Similar to conclude, notifies principles when the axium is open to their emissions. Part of the initialization, addConcept, and removeConcept strategies.
* axiumClose - This will will cancel all internal subscriptions that the axium has access to. As well as all Steams will be completed. The external close() function that the createAxium supplies, dispatches this action. Or can be ran specially via an internal principle towards its governing axium or that of another axium that it is subscribed to.
* axiumRemoveConceptsViaQue - This will run via the internal axium principle. Whenever there is an addition to this remove que.
## Use With Care
*These are part of the add and remove concept strategies. And while internal could be used if required.*
* setBlockingMode - Sets the mode to blocking and open to False. This would notify any principles to cease detecting for changes. This is part of the add and remove concept strategies. And while internal could be used if required.
* setDefaultMode - Sets the modeIndex to the defaultModeIndex and open to True. This informs principles that it is clear to detect changes.
* axiumSetBlockingMode - Sets the mode to blocking and open to False. This would notify any principles to cease detecting for changes. This is part of the add and remove concept strategies. And while internal could be used if required.
* axiumSetDefaultMode - Sets the modeIndex to the defaultModeIndex and open to True. This informs principles that it is clear to detect changes.
## Useful Axium Qualities
* open - Sets axium open property by default to True if no payload is supplied. Must be used after setBlockingMode in a strategy to reenable functionality of principles and external subscribers.
* log - Merely Logs the action, is useful for debugging ActionStrategies as it logs attached Strategy, its current ActionList, and any addition action qualities.
* preClose - Will prompt the axium to close and disengage all active subscriptions, while notifying subscribers that their concept has been removed.
* setMode - If your concept requires a specific modification to the functionality of the stream. This will set the mode index to that stream. Specifically this shouldn't have to be used. But is left to the developer if they run into such a case.
* setDefaultModeIndex - Should be used if your mode is to be considered the default mode of your application. For utilization within a strategy after setMode. Be sure to a run time search for your concept name and mode, after your concept is added via the addConcept strategy found below. Be mindful that modeName is just your Concept Name and the creation of new Modes should be the last go To for your applications functionality.
* clearDialog - Clears the currently stored Stratimux dialog, may be used within a strategy.
* clearBadActionTypeFromBadActionList - This is to allow for plans to take into account for expired actions and clear such.
* clearBadStrategyTopicFromBadActionList - Allows plans to accounts for specific ActionStrategy topics that might find themselves in badActions and clear such.
* clearBadPlanFromBadPlanList - This additionally allows for concepts to take into account potentially failed plans that are set by axium.plan(). Via their topic as payload and clears such.
* kick - This is a pure action that will just trigger the next function via the UnifiedSubject to prime subscribers or stages. Noting that the downside of Stratimux's halting quality, is you have to kick it into gear if it hasn't received an action recently for your staged Plans to operate as intended.
* axiumOpen - Sets axium open property by default to True if no payload is supplied. Must be used after setBlockingMode in a strategy to reenable functionality of principles and external subscribers.
* axiumLog - Merely Logs the action, is useful for debugging ActionStrategies as it logs attached Strategy, its current ActionList, and any addition action qualities.
* axiumPreClose - Will prompt the axium to close and disengage all active subscriptions, while notifying subscribers that their concept has been removed.
* axiumSetMode - If your concept requires a specific modification to the functionality of the stream. This will set the mode index to that stream. Specifically this shouldn't have to be used. But is left to the developer if they run into such a case.
* axiumSetDefaultModeIndex - Should be used if your mode is to be considered the default mode of your application. For utilization within a strategy after setMode. Be sure to a run time search for your concept name and mode, after your concept is added via the addConcept strategy found below. Be mindful that modeName is just your Concept Name and the creation of new Modes should be the last go To for your applications functionality.
* axiumClearDialog - Clears the currently stored Stratimux dialog, may be used within a strategy.
* axiumClearBadActionTypeFromBadActionList - This is to allow for plans to take into account for expired actions and clear such.
* axiumClearBadStrategyTopicFromBadActionList - Allows plans to accounts for specific ActionStrategy topics that might find themselves in badActions and clear such.
* axiumClearBadPlanFromBadPlanList - This additionally allows for concepts to take into account potentially failed plans that are set by axium.plan(). Via their topic as payload and clears such.
* axiumKick - This is a pure action that will just trigger the next function via the UnifiedSubject to prime subscribers or stages. Noting that the downside of Stratimux's halting quality, is you have to kick it into gear if it hasn't received an action recently for your staged Plans to operate as intended.
* axiumRegisterTimeOut - This will call the axiumTimeOut function on the incoming payload's act and timeOut properties. Then will succeed a strategy if present.
## Axium Strategies Concept Set Transformation
```typescript
Expand Down
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,10 @@ When in doubt simplify.
* [Unified Turing Machine](https://github.com/Phuire-Research/Stratimux/blob/main/The-Unified-Turing-Machine.md) - The governing concept for this entire framework.

## Change Log ![Tests](https://github.com/Phuire-Research/Stratimux/actions/workflows/node.js.yml/badge.svg)
### Consistency Update v0.1.71 5/16/2024
### *Consistency Update* v0.1.72
* Added a new Axium Quality: **axiumRegisterTimeOut**, that accepts an action and specified timeout that will run the axiumTimeOut function then succeed an incoming strategy if present.
* This likewise fulfills the original purpose of buffer, even in a complex scenario.
### v0.1.71 5/16/2024
* Finally removed the need to add "as Subject<Concepts> | UnifiedSubject" when creating methods that access state or concepts.
* Added then **removed** a new Buffer Method Creator Series. See branch Stash-Buffer for details.
### v0.1.69 5/15/2024
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "stratimux",
"license": "GPL-3.0",
"version": "0.1.71",
"version": "0.1.72",
"description": "Unified Turing Machine",
"main": "dist/index.js",
"module": "dist/index.mjs",
Expand Down
6 changes: 4 additions & 2 deletions src/concepts/axium/axium.concept.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import { axiumRegisterStagePlannerQuality } from './qualities/registerStagePlann
import { axiumKickQuality } from './qualities/kick.quality';
import { axiumPreCloseQuality } from './qualities/preClose.quality';
import { axiumStitchQuality } from './qualities/stitch.quality';
import { axiumRegisterTimeOutQuality } from './qualities/registerTimeOut.quality';

export type NamedSubscription = {
name: string;
Expand Down Expand Up @@ -73,7 +74,7 @@ export type AxiumState = {
badPlans: Plan[];
badActions: Action[];
timer: NodeJS.Timeout[];
timerLedger: Map<number, [(() => Action)[], number]>
timerLedger: Map<number, (() => Action)[]>
head: Action[];
body: Action[];
tail: Action[];
Expand Down Expand Up @@ -148,7 +149,8 @@ export const createAxiumConcept = (name: string, storeDialog?: boolean, logging?
axiumClearBadActionTypeFromBadActionListQuality,
axiumClearBadStrategyTopicFromBadActionListQuality,
axiumClearBadPlanFromBadPlanListQuality,
axiumStitchQuality
axiumStitchQuality,
axiumRegisterTimeOutQuality
],
[axiumPrinciple, axiumClosePrinciple],
[blockingMode, permissiveMode]
Expand Down
40 changes: 40 additions & 0 deletions src/concepts/axium/qualities/registerTimeOut.quality.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*<$
For the asynchronous graph programming framework Stratimux and Axium Concept,
generate a quality that will register a subscription to the concepts$ stream.
This allows for the clean closure of concepts that are removed or when the axium itself exits.
$>*/
/*<#*/
import { defaultReducer, nullReducer } from '../../../model/concept';
import { selectPayload } from '../../../model/selector';
import { createQualitySetWithPayload } from '../../../model/quality';
import { createMethodWithConcepts } from '../../../model/method';
import { axiumTimeOut } from '../../../model/time';
import { Action } from '../../../model/action';
import { strategySuccess } from '../../../model/actionStrategy';

export type AxiumRegisterTimeOutPayload = {
act: Action;
timeOut: number
}

export const [
axiumRegisterTimeOut,
axiumRegisterTimeOutType,
axiumRegisterTimeOutQuality
] = createQualitySetWithPayload<AxiumRegisterTimeOutPayload>({
type: 'register an Action to Axium\'s timerLedger',
reducer: defaultReducer,
methodCreator: (concepts$, semaphore) => createMethodWithConcepts((action, concepts) => {
const {
act,
timeOut
} = selectPayload<AxiumRegisterTimeOutPayload>(action);
axiumTimeOut(concepts, () => act, timeOut);
if (action.strategy) {
return strategySuccess(action.strategy);
} else {
return action;
}
}, concepts$, semaphore)
});
/*#>*/
17 changes: 13 additions & 4 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -171,15 +171,25 @@ export {
AxiumRegisterStagePlannerPayload,
axiumRegisterStagePlannerType
} from './concepts/axium/qualities/registerStagePlanner.quality';
export { axiumClearDialog, axiumClearDialogType } from './concepts/axium/qualities/clearDialog.quality';
export { axiumSetDefaultMode,
export {
axiumClearDialog,
axiumClearDialogType
} from './concepts/axium/qualities/clearDialog.quality';
export {
axiumSetDefaultMode,
axiumSetDefaultModeType,
AxiumSetDefaultModePayload
} from './concepts/axium/qualities/setDefaultMode.quality';
export { axiumSetBlockingMode,
export {
axiumSetBlockingMode,
axiumSetBlockingModeType,
AxiumSetBlockingModePayload
} from './concepts/axium/qualities/setBlockingMode.quality';
export {
axiumRegisterTimeOut,
AxiumRegisterTimeOutPayload,
axiumRegisterTimeOutType
} from './concepts/axium/qualities/registerTimeOut.quality';
// Strategies
export {
addConceptsToAddQueThenBlockStrategy,
Expand All @@ -189,7 +199,6 @@ export {
addConceptsToRemovalQueThenBlockStrategy,
addConceptsToRemovalQueThenBlockTopic
} from './concepts/axium/strategies/removeConcept.strategy';

// Counter
export { CounterState, counterName, createCounterConcept } from './concepts/counter/counter.concept';
export { counterSelectCount } from './concepts/counter/counter.selector';
Expand Down
39 changes: 25 additions & 14 deletions src/model/time.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,16 @@ const handleTimedRun = (axiumState: AxiumState, func: (() => Action)[], timed: n
});
axiumState.timer.shift();
axiumState.timerLedger.delete(timed);
const timerKeys = Object.keys(axiumState.timerLedger);
const timerKeys: number[] = [];
axiumState.timerLedger.forEach((_, key) => {
timerKeys.push(key);
});
if (timerKeys.length > 0) {
const timerList = timerKeys.map(t => Number(t)).sort((a, b) => a - b);
const timerList = timerKeys.sort((a, b) => a - b);
const slot = axiumState.timerLedger.get(timerList[0]);
if (slot) {
const someTime = slot[1] - Date.now();
axiumState.timer.push(setTimeout(() => handleTimedRun(axiumState, slot[0], slot[1]), someTime >= 0 ? someTime : 0));
const someTime = timerList[0] - Date.now();
axiumState.timer.push(setTimeout(() => handleTimedRun(axiumState, slot, timerList[0]), someTime >= 0 ? someTime : 0));
}
}
if (axiumState.tailTimer.length === 0) {
Expand All @@ -48,35 +51,43 @@ export const axiumTimeOut = (concepts: Concepts, func: () => Action, timeOut: nu
const timer = axiumState.timer.length > 0 ? axiumState.timer[0] : undefined;
if (timer) {
// If timer exists, first index of timerList would exist
const timerList = Object.keys(ledger).map(t => Number(t)).sort((a, b) => a - b);
const timerKeys: number[] = [];
axiumState.timerLedger.forEach((_, key) => {
timerKeys.push(key);
});
const timerList = timerKeys.sort((a, b) => a - b);
if (timerList[0] > timed) {
clearTimeout(timer);
axiumState.timer.shift();
const slot = axiumState.timerLedger.get(timed);
if (slot) {
slot[0].push(func);
ledger.set(timed, [slot[0], timed]);
slot.push(func);
axiumState.timer.push(setTimeout(() => {
handleTimedRun(axiumState, slot[0], timed);
handleTimedRun(axiumState, slot, timed);
}, timeOut));
} else {
ledger.set(timed, [[func], timed]);
ledger.set(timed, [func]);
const slotted = ledger.get(timed) as (() => Action)[];
axiumState.timer.push(setTimeout(() => {
handleTimedRun(axiumState, [func], timed);
handleTimedRun(axiumState, slotted, timed);
}, timeOut));
}
} else {
const slot = axiumState.timerLedger.get(timed);
if (slot) {
slot[0].push(func);
ledger.set(timed, [slot[0], timed]);
slot.push(func);
ledger.set(timed, slot);
} else {
ledger.set(timed, [func]);
}
}
} else {
ledger.set(timed, [[func], timed]);
ledger.set(timed, [func]);
const slotted = ledger.get(timed) as (() => Action)[];
axiumState.timer.push(setTimeout(() => {
handleTimedRun(axiumState, [func], timed);
handleTimedRun(axiumState, slotted, timed);
}, timeOut));
}
};

/*#>*/
73 changes: 73 additions & 0 deletions src/test/axiumRegisterTimeOut/axiumRegisterTimeOut.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/*<$
For the asynchronous graph programming framework Stratimux, generate a tests and demonstrates how register timeout quality functions.
$>*/
/*<#*/
import { axiumKick } from '../../concepts/axium/qualities/kick.quality';
import { axiumRegisterTimeOut } from '../../concepts/axium/qualities/registerTimeOut.quality';
import { CounterState, counterName, createCounterConcept } from '../../concepts/counter/counter.concept';
import { counterSelectCount } from '../../concepts/counter/counter.selector';
import { counterAdd } from '../../concepts/counter/qualities/add.quality';
import { createAxium } from '../../model/axium';
import { selectState } from '../../model/selector';
import { createStage, stageWaitForOpenThenIterate } from '../../model/stagePlanner';

test('Axium Register Time Out', (done) => {
const axium = createAxium('timeout defer actions', [createCounterConcept()]);
const plan = axium.plan('timeout add 4 after 10ms', [
stageWaitForOpenThenIterate(() => axiumKick()),
createStage((_, dispatch) => {
dispatch(axiumRegisterTimeOut({
act: counterAdd(),
timeOut: 50
}), {
iterateStage: true,
});
}),
createStage((concepts, dispatch) => {
const counterState = selectState<CounterState>(concepts, counterName);
expect(counterState?.count).toBe(0);
dispatch(axiumRegisterTimeOut({
act: counterAdd(),
timeOut: 50
}), {
iterateStage: true,
});
}),
createStage((concepts, dispatch) => {
const counterState = selectState<CounterState>(concepts, counterName);
expect(counterState?.count).toBe(0);
dispatch(axiumRegisterTimeOut({
act: counterAdd(),
timeOut: 50
}), {
iterateStage: true,
});
}),
createStage((concepts, dispatch) => {
const counterState = selectState<CounterState>(concepts, counterName);
expect(counterState?.count).toBe(0);
dispatch(axiumRegisterTimeOut({
act: counterAdd(),
timeOut: 50
}), {
iterateStage: true,
});
}),
createStage((concepts, _dispatch, changes) => {
const counterState = selectState<CounterState>(concepts, counterName);
if (changes.length > 0) {
expect(counterState?.count).toBe(4);
setTimeout(() => {
plan.conclude();
axium.close();
done();
}, 10);
}
}, {selectors: [counterSelectCount], beat: 200}),
createStage(() => {
plan.conclude();
})
]);
});

/*#>*/

0 comments on commit 1c0666a

Please sign in to comment.