Skip to content

Commit

Permalink
Refinement and adjusted terminology towards plan
Browse files Browse the repository at this point in the history
  • Loading branch information
REllEK-IO committed Oct 11, 2023
1 parent 5d73940 commit 8ae4250
Show file tree
Hide file tree
Showing 9 changed files with 49 additions and 27 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ const axium = createAxium('ownershipTest', [
createCounterConcept(),
createExperimentConcept(createExperimentActionQueState(), [checkInQuality], [experimentActionQuePrinciple])
], true, true);
const staged = axium.stage(
const plan = axium.stage(
'Testing Ownership Staging', [
(cpts, dispatch) => {
const axiumState = cpts[0].state as AxiumState;
Expand Down
41 changes: 30 additions & 11 deletions Stage.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
## Stage
### Abstract
This is derived from the newly created UnifiedSubject to handle the main point of vulnerability that a recursive machine carries. As the main point of dispatching new actions in the system would traditionally be informed via the subscription to listen to state changes. This Design Pattern allows one to safely dispatch in a tightly patterned subscription. This design pattern watches each stage for the potential of a runaway configuration which would normally prevent this machine from halting. But since the Unified Turing Machine was created to be halting complete. The UnifiedSubject internally watches each stage of your application independently and the actions that it dispatches via the supplied dispatch function. If a similar action is dispatched in rapid Succession denoted by its type and no debounce option. That Stage will close and be added to the axium's badPlans property.
This is derived from the newly created UnifiedSubject to handle the main point of vulnerability that a recursive machine carries. As the main point of dispatching new actions in the system would traditionally be informed via the subscription to listen to state changes. This Design Pattern allows one to safely dispatch in a tightly patterned subscription. This design pattern watches each stage for the potential of a runaway configuration which would normally prevent this machine from halting. But since the Unified Turing Machine was created to be halting complete. The UnifiedSubject internally watches each stage of your application independently and the actions that it dispatches via the supplied dispatch function. If a similar action is dispatched in rapid Succession denoted by its type and no debounce option. That plan will conclude and be added to the axium's badPlans property.

Once attached to the badPlan property, it would be possible to reinitialize said stage via your concept's principle utilizing the stage's title. But places that burden of responsibility on the developer. As the scope of a Unified Turing Machine is to be designed to specification and halt appropriately. We accept failure as likewise the ability to halt.

"You stage a plan and a plan has multiple stages."
*"You stage a plan and a plan has multiple stages."*

## Working with the Stage Paradigm
The added benefit of the creation of a plan to control the flow of actions. Allows the ability to create a series of stages to handle how the dispatch would be handled within a subscription, but with the added benefit of iterating through each stage your plan. A typical plan would typically be composed of an initialization, main run time, and likewise the ability to close. 3 acts if you will.
The added benefit of the creation of a plan to control the flow of actions. Allows the ability to create a series of stages to handle how the dispatch would be handled within a subscription, but with the added benefit of iterating through each stage your plan. A typical plan would typically be composed of an initialization, main run time, and likewise the ability to conclude. 3 acts if you will.
```typescript
// Multiple Stages are a Plan
export type Plan = {
Expand Down Expand Up @@ -41,16 +41,14 @@ export type dispatchOptions = {
* incrementStage - Will increment to the next stage index, this should be your default option for dispatching actions or strategies to prevent action overflow.
* setStage - This will set the stage to a specific stage index, useful if some strategy failed and the staging needs to be reset to prepare for that strategy again. This will always override iterateStage.
* on - Simple handler that will prevent dispatch until the selected value is set to what is expected. Keep in mind this should also be occupied by a debounce, as this dispatch will run on each successful state update. This should be utilized alongside iterateStage, setStage, or debounce to prevent action overflow.

*Note* To prevent action overflow, each stage is paying attention to consecutive actions.

### Internals
```typescript
export type Dispatcher = (action: Action, options: dispatchOptions) => void;
export type Staging = (
concepts: Concept[],
dispatch: (action: Action, options: dispatchOptions) => void
) => void;

export class UnifiedSubject extends Subject<Concept[]> {
stage(title: string, stages: Staging[]) {}
}
Expand All @@ -69,14 +67,14 @@ const sub = axium.subscribe((concepts) => {
const badPlan = axiumState.badPlans[0];
const counter = selectState<Counter>(concepts, counterName);
console.log('Stage Ran Away, badPlans.length: ', axiumState.badPlans.length, 'Count: ', counter.count);
staged.close();
plan.conclude();
sub.unsubscribe();
expect(badPlan.stageFailed).toBe(2);
expect(counter.count).toBe(2);
setTimeout(() => {done();}, 500);
}
});
const staged = axium.stage('Stage DispatchOptions Test',
const plan = axium.stage('Stage DispatchOptions Test',
[
(concepts, dispatch) => {
const counter = selectState<Counter>(concepts, counterName);
Expand Down Expand Up @@ -107,19 +105,40 @@ const staged = axium.stage('Stage DispatchOptions Test',
runCount++;
const counter = selectState<Counter>(concepts, counterName);
console.log('Should run twice, Stage 3 ', counter, runCount);
// Will cause an action overflow forcing the stage to close and add itself to badPlans
// Will cause an action overflow forcing the current stage to conclude and add the plan to badPlans
dispatch(counterSubtract(), {
// Enabling will cause this test to timeout via the subscription watching for badPlans to never be ran.
// debounce: 500
// This demonstrates the fault resistance of the Stage paradigm, despite STRX's recursive functionality.
});
// This dispatch will be invalidated and never dispatched due to the effect of action overflow of the above.
dispatch(counterAdd(), {});
console.log('Should run twice. 1st will be before "Stage Ran Away," and 2nd will be final console log output.');
console.log(
'Will also run twice. 1st will be before "Stage Ran Away,"',
'and after "Should run twice." The 2nd will be final console log output.'
);
}
]);
```
To prevent action overflow, each stage is paying attention to consecutive actions of the same type. In an action overflow state, sequentially the overflow will call the same dispatch before called the next dispatch even if within the same stage.

Keep in mind behind the scenes during a STRX runtime, there will be multiple strategies running concurrently. Observe the runCount specified in this example. Please look to the STRX's tests folder.

As well that STRX is designed to be run primarily through the loaded concepts and their associated principles. To prevent unexpected behaviors in your own principles. Please utilize the supplied KeyedSelector for axium's open property to begin the stage of your concepts.
## Stage within your Principle
STRX is designed to be ran primarily through its loaded concepts and their associated principles. To prevent unexpected behaviors in your own principles. Please utilize the supplied KeyedSelector for axium's open property to begin the stage of your concepts.
```typescript
const plan = concept$.stage('Principle Stage Example', [
(___, dispatch) => {
dispatch(someAction(), {
iterateStage: true,
on: {
selector: axiumSelectOpen,
expected: true
},
});
},
(concepts, dispatch) => {
// Your principle's run time logic.
}
]);
```
4 changes: 2 additions & 2 deletions src/model/unifiedSubject.ts
Original file line number Diff line number Diff line change
Expand Up @@ -143,11 +143,11 @@ export class UnifiedSubject extends Subject<Concept[]> {
this.currentStages.set(this.stageId, {title, stages, stage: 0, stageFailed: -1});
const stageId = this.stageId;
this.stageId++;
const close = () => {
const conclude = () => {
this.currentStages.delete(stageId);
};
return {
close: close.bind(this)
conclude: conclude.bind(this)
};
}

Expand Down
4 changes: 2 additions & 2 deletions src/test/addConcepts.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { countingTopic } from '../concepts/counter/strategies/counting.strategy'

test('Axium add Concepts Strategy Test', (done) => {
const axium = createAxium('axiumAddConceptTest',[], true, true);
const staged = axium.stage('Add Concepts Stage',[
const plan = axium.stage('Add Concepts Stage',[
(concepts, dispatch) => {
dispatch(
strategyBegin(
Expand All @@ -36,7 +36,7 @@ test('Axium add Concepts Strategy Test', (done) => {
const counter = selectState<Counter>(concepts, counterName);
expect(counter.count).toBe(1);
setTimeout(() => {done();}, 500);
staged.close();
plan.conclude();
}
}
]);
Expand Down
4 changes: 2 additions & 2 deletions src/test/ownership.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ test('Ownership Test', (done) => {
createCounterConcept(),
createExperimentConcept(createExperimentActionQueState(), [checkInQuality], [experimentActionQuePrinciple])
], true, true);
const staged = axium.stage(
const plan = axium.stage(
'Testing Ownership Staging', [
(cpts, dispatch) => {
const axiumState = cpts[0].state as AxiumState;
Expand Down Expand Up @@ -70,7 +70,7 @@ test('Ownership Test', (done) => {
expect(counter.count).toBe(3);
// Comment in if testing the halting ability of log and setCount stage is commented out.
// setTimeout(() => {done();}, 1000);
staged.close();
plan.conclude();
} else if (
(axiumState.lastStrategy === experimentCountingTopic ||
axiumState.lastStrategy === experimentPrimedCountingTopic) &&
Expand Down
4 changes: 2 additions & 2 deletions src/test/removeConcepts.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { AxiumState } from '../concepts/axium/axium.concept';

test('Axium remove Concepts Strategy Test', (done) => {
const axium = createAxium('axiumRemoveConceptsTest', [createCounterConcept()], true, true);
const staged = axium.stage('Remove Concepts Stage',[
const plan = axium.stage('Remove Concepts Stage',[
(concepts, dispatch) => {
dispatch(
strategyBegin(
Expand All @@ -33,7 +33,7 @@ test('Axium remove Concepts Strategy Test', (done) => {
});
expect(exists).toBe(false);
setTimeout(() => {done();}, 500);
staged.close();
plan.conclude();
}
}
]);
Expand Down
9 changes: 6 additions & 3 deletions src/test/stageDispatchOptions.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,14 @@ test('Axium Stage Dispatch Options Test', (done) => {
const badPlan = axiumState.badPlans[0];
const counter = selectState<Counter>(concepts, counterName);
console.log('Stage Ran Away, badPlans.length: ', axiumState.badPlans.length, 'Count: ', counter.count);
staged.close();
plan.conclude();
sub.unsubscribe();
expect(badPlan.stageFailed).toBe(2);
expect(counter.count).toBe(2);
setTimeout(() => {done();}, 500);
}
});
const staged = axium.stage('Stage DispatchOptions Test',
const plan = axium.stage('Stage DispatchOptions Test',
[
(concepts, dispatch) => {
const counter = selectState<Counter>(concepts, counterName);
Expand Down Expand Up @@ -61,7 +61,10 @@ test('Axium Stage Dispatch Options Test', (done) => {
});
// This dispatch will be invalidated and never dispatched due to the effect of action overflow of the above.
dispatch(counterAdd(), {});
console.log('Should run twice. 1st will be before "Stage Ran Away," and 2nd will be final console log output.');
console.log(
'Will also run twice. 1st will be before "Stage Ran Away,"',
'and after "Should run twice." The 2nd will be final console log output.'
);
}
]);
});
4 changes: 2 additions & 2 deletions src/test/stagedPrinciple.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ const experimentMockToTrueQuality = createQuality(experimentMockToTrueType, expe

test('Axium Principle Stage', (done) => {
const experimentPrinciple: PrincipleFunction = (_: Subscriber<Action>, __: Concept[], concept$: UnifiedSubject) => {
const stage = concept$.stage('Experiment Principle', [
const plan = concept$.stage('Experiment Principle', [
(___, dispatch) => {
dispatch(experimentMockToTrue(), {
iterateStage: true,
Expand All @@ -41,7 +41,7 @@ test('Axium Principle Stage', (done) => {
if (experimentState.mock) {
expect(experimentState.mock).toBe(true);
setTimeout(() => done(), 1000);
stage.close();
plan.conclude();
}
}
]);
Expand Down
4 changes: 2 additions & 2 deletions src/test/strategy.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { countingTopic } from '../concepts/counter/strategies/counting.strategy'

test('Axium Counting Strategy Test', (done) => {
const axium = createAxium('axiumStrategyTest', [createCounterConcept()], true, true);
const staged = axium.stage('Counting Strategy Stage',
const plan = axium.stage('Counting Strategy Stage',
[
(_, dispatch) => {
dispatch(strategyBegin(countingStrategy()), {
Expand All @@ -20,7 +20,7 @@ test('Axium Counting Strategy Test', (done) => {
const counter = selectState<Counter>(concepts, counterName);
expect(counter.count).toBe(1);
setTimeout(() => {done();}, 500);
staged.close();
plan.conclude();
}
}
]);
Expand Down

0 comments on commit 8ae4250

Please sign in to comment.