Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Consistency v0.1.64 #215

Merged
merged 4 commits into from
May 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 18 additions & 4 deletions ActionStrategy.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,20 +29,26 @@ ActionNode represents some node that is capable of being turned into some action
export interface ActionNode {
action?: Action;
actionType: ActionType;
payload?: unknown;
payload?: Record<string, unknown>;
conceptSemaphore?: number;
priority?: number;
keyedSelectors?: KeyedSelector[];
semaphore?: [number, number, number];
semaphore?: [number, number, number, number];
agreement?: number;
decisionNodes?: Record<string, ActionNode>;
decisionNotes?: ActionNotes;
successNode: ActionNode | null;
successNotes?: ActionNotes;
failureNode: ActionNode | null;
preposition?: string;
denoter?: string;
failureNotes?: ActionNotes;
lastActionNode?: ActionNode;
}

// Used via the createActionNode function.
export interface ActionNodeOptions {
keyedSelectors?: KeyedSelector[];
conceptSemaphore?: number;
priority?: number;
semaphore?: [number, number, number, number];
agreement?: number;
decisionNodes?: Record<string, ActionNode>;
Expand All @@ -54,16 +60,24 @@ export interface ActionNodeOptions {
lastActionNode?: ActionNode;
}

export interface ActionNotes {
preposition?: string;
denoter?: string;
}
```
* action - Is an union data pattern to bind the functionality of the ActionNode, ActionStrategy, and Action. This allows for each part to be responsible for itself and to allow for additional functionality at runtime.
* actionType - Is merely the type of action to be created at runtime, these should be verbose as to their intended effect as it informs the Stratimux sentence structure's body.
* payload - Is set to unknown to allow for the explicit typecasting during consumption, reducer, method, or principle. Be sure to import actions directly to ensure payload type safety in the reducer. This is a logical determination in line with Javascript core functionality.
* conceptSemaphore - Used when dispatching to a foreign Axium. Where the effecting action will trigger on some unified concept on such that the current axium has observation of.
* priority - By default all action's dispatched via quality observations will be pushed to the end of the tail que on the Axium. By setting this value, it will force the handlePriority internal function to trigger and assign the action to the determined slot on the body que instead.
* keyedSelectors - An Array of KeyedSelector that locks some property during the life time of the created action.
* semaphore - First is concept's index, second is the quality's index, and the final is the generation of the sets of concepts currently stored on the Axium. *Explicitly setting this value, denotes a primed action without additional look up at runtime.*
* agreement - Is time in milliseconds of the lock's expiration time. Default is currently 5000, but such will be reduced upon testing and feedback.
* decisionNodes - Is a record of all possible decisions that the ActionNode may take depending upon some test. And should be seen as a replacement for SuccessNode if utilized. This is what makes the ActionStrategy capable of complexity beyond squared.
* successNode - Is the default chain of actions. Can be replaced by decisionNodes to enable additional behaviors.
* failureNode - Is the default failure mode of each action. And will be called if ownership is loaded in an axium. If null the ActionStrategy will conclude which will free the current lock supplied. Otherwise it will be added to the pendingActions que.

**ActionNotes**
* preposition - Coincides with the Stratimux sentence structure. And is the logical linking between the previous sentences and the current ActionType.
* denoter - Also enhances the Stratimux sentence as either a punctuation mark or additional description of the ActionType's intended effect.
*NOTE: Just like all optional fields, except action, these are designed to be set at runtime if dynamic or can be prefilled if the values are known prior.*
Expand Down
13 changes: 13 additions & 0 deletions Axium.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ The design decision here allows us to forgo the need for dependency injection. A

```typescript
export type AxiumState = {
// Would be unique identifier on a network
name: string;
open: boolean;
prepareClose: boolean;
Expand Down Expand Up @@ -58,6 +59,12 @@ export type AxiumState = {
removeConceptQue: Concept[],
badPlans: Plan[];
badActions: Action[];
timer: NodeJS.Timeout[];
timerLedger: Map<number, [(() => Action)[], number]>
head: Action[];
body: Action[];
tail: Action[];
tailTimer: NodeJS.Timeout[];
}
```
* name - This should be set to a unique network identifier, and/or the concept of your system.
Expand Down Expand Up @@ -87,6 +94,12 @@ export type AxiumState = {
* removeConceptQue - The inverse of the above to remove concepts.
* badPlans - Stores plans that have experienced action overflow.
* badActions - Keeps track of all actions that cannot be registered via the cachedSemaphores property.
* timer - This internal timer is set via the timerLedger, each subsequent call creating a new timer that is held as the only entry in this array.
* timerLedger - Is modified when using axiumTimeOut, that will assign a callback function that returns an action to be used in a single setTimeout function.
* head - A single action is allowed to exist in the head and ensures that the axium performs a lock step sequence of actions.
* body - Mostly updated via plans. Taking precedent to actions that are issued via ActionStrategies or the axiumTimeOut functionality unless the correlated actions have some priority. Then such are assigned to the body que, ordering the body according to each action's priority or prior placement.
* tail - The final que to be called when body has been depleted. This is a low priority que that is informed via qualities via the axiumTimeOut method.
* tailTimer - This timer will be enabled each time a tail entry has been assigned, but will be cleared each time an action enters the action stream.

## The Anatomy of an Axium
* Action - Is a dumb object that is supplied some data as payload or performs some transformation of state based on its semaphore which is inferred via its type. Is the messaging protocol of an axium.
Expand Down
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +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)
### v0.1.64 5/13/2024
* Added Action Priority: This will allow action's assigned a priority of not 0 to be placed accordingly into the action ques.
* Adjusted DotPath type to improve type checking performance. Massively degrades with an additional level.
* Updated documentation to reflect recent changes
### Patch v0.1.62 5/09/2024
* Restored DotPath, a type used in the selector creators used to guide the creation of a dot path string.
### **BREAKING** Strong Fast Lock Step v0.1.62 5/08/2024
Expand Down
24 changes: 24 additions & 0 deletions StagePlanner.md
Original file line number Diff line number Diff line change
Expand Up @@ -196,3 +196,27 @@ const plan = concept$.plan('Principle Stage Example', [
})
]);
```
## How Stage Priority effects Actions
Whenever an action is dispatched into the action stream. They are checked into an action que system. By default any priority assigned to a stage, will likewise associate that to an action. This assumes that the stage itself is taking priority in observation and action when set.

If you require a high priority observation, but want the action ques to deplete accordingly without effecting such. Set the action's priority to 0. This will cause the internal checks to skip over handling that action's priority. Otherwise if such is set to undefined, then the dispatching stage's priority will once again be set.

```typescript
// Will have high observation priority, but no action priority.
createStage((_, dispatch) => {
const action = axiumKick();
action.priority = 0;
dispatch(action, {
iterateStage: true
});
}, {priority: 100})

// No observation priority, but high action priority.
createStage((_, dispatch) => {
const action = axiumKick();
action.priority = 100;
dispatch(action, {
iterateStage: true
});
})
```
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.63",
"version": "0.1.64",
"description": "Unified Turing Machine",
"main": "dist/index.js",
"module": "dist/index.mjs",
Expand Down
8 changes: 4 additions & 4 deletions src/concepts/axium/axium.concept.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,18 +66,18 @@ export type AxiumState = {
generalSubscribers: NamedSubscription[];
stagePlanners: NamedStagePlanner[];
action$: Subject<Action>;
head: Action[];
body: Action[];
tail: Action[];
actionConcepts$: Subject<Concepts>;
concepts$: UnifiedSubject;
addConceptQue: Concept[],
removeConceptQue: Concept[],
badPlans: Plan[];
badActions: Action[];
timer: NodeJS.Timeout[];
tailTimer: NodeJS.Timeout[];
timerLedger: Map<number, [(() => Action)[], number]>
head: Action[];
body: Action[];
tail: Action[];
tailTimer: NodeJS.Timeout[];
}

export const axiumName = 'axium';
Expand Down
4 changes: 2 additions & 2 deletions src/concepts/axium/axium.principle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ export const axiumPrinciple: PrincipleFunction = (
quality.toString = qualityToString(quality);
const methodSub = quality.method.subscribe(([act, _]) => {
const tail = getAxiumState(concepts).tail;
blockingMethodSubscription(tail, act);
blockingMethodSubscription(concepts, tail, act);
}) as Subscriber<Action>;
getAxiumState(concepts).methodSubscribers.push({name: concept.name, subscription: methodSub});
}
Expand Down Expand Up @@ -153,7 +153,7 @@ export const axiumPrinciple: PrincipleFunction = (
return caught;
}));
const methodSub = quality.method.subscribe(([action, _]) => {
blockingMethodSubscription(axiumState.tail, action);
blockingMethodSubscription(newConcepts, axiumState.tail, action);
}) as Subscriber<Action>;
const _axiumState = newConcepts[0].state as AxiumState;
_axiumState.methodSubscribers.push({
Expand Down
2 changes: 1 addition & 1 deletion src/concepts/axium/qualities/setBlockingMode.quality.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export const [
if (quality.method) {
const sub = quality.method.subscribe(([action, _]) => {
const tail = state.tail;
blockingMethodSubscription(tail, action);
blockingMethodSubscription(concepts, tail, action);
});
methodSubscribers.push({
name: concept.name,
Expand Down
30 changes: 23 additions & 7 deletions src/model/action.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ export type Action = {
agreement?: number;
expiration: number;
axium?: string;
priority?: number;
};

const createPayload = <T extends Record<string, unknown>>(payload: T) => payload;
Expand Down Expand Up @@ -172,7 +173,8 @@ export function createAction<T extends Record<string, unknown>>(
keyedSelectors?: KeyedSelector[],
agreement?: number,
_semaphore?: [number, number, number, number],
conceptSemaphore?: number
conceptSemaphore?: number,
priority?: number
): Action {
const special = getSpecialSemaphore(type);
const semaphore = _semaphore !== undefined ? _semaphore : [0, 0, -1, special] as [number, number, number, number];
Expand All @@ -183,7 +185,8 @@ export function createAction<T extends Record<string, unknown>>(
keyedSelectors,
agreement,
expiration: Date.now() + (agreement !== undefined ? agreement : 5000),
conceptSemaphore
conceptSemaphore,
priority
};
}

Expand All @@ -199,9 +202,18 @@ export function prepareActionCreator(actionType: ActionType) {
conceptSemaphore?: number,
keyedSelectors?: KeyedSelector[],
agreement?: number,
qualitySemaphore?: [number, number, number, number]
qualitySemaphore?: [number, number, number, number],
priority?: number
) => {
return createAction(actionType, undefined, keyedSelectors, agreement, qualitySemaphore, conceptSemaphore);
return createAction(
actionType,
undefined,
keyedSelectors,
agreement,
qualitySemaphore,
conceptSemaphore,
priority
);
};
}

Expand All @@ -211,17 +223,21 @@ export function prepareActionWithPayloadCreator<T extends Record<string, unknown
conceptSemaphore?: number,
keyedSelectors?: KeyedSelector[],
agreement?: number,
semaphore?: [number, number, number, number]
semaphore?: [number, number, number, number],
priority?: number
): Action => {
return createAction(actionType, payload, keyedSelectors, agreement, semaphore, conceptSemaphore);
return createAction(
actionType,
payload, keyedSelectors, agreement, semaphore, conceptSemaphore, priority);
};
}
export type ActionCreatorWithPayload<T> = (
payload: T,
conceptSemaphore?: number,
keyedSelectors?: KeyedSelector[],
agreement?: number,
semaphore?: [number, number, number, number]
semaphore?: [number, number, number, number],
priority?: number
) => Action;

/**
Expand Down
9 changes: 8 additions & 1 deletion src/model/actionStrategy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import { KeyedSelector } from './selector';
* @param payload - `optional` Will set the payload of the action.
* @param semaphore - `optional` This will prime the action to avoid look up at run time. Best practice use getSemaphore().
* @param conceptSemaphore - `optional` Used for Unified Qualities. Must be specified via that principle's passed semaphore value.
* @param priority - `optional` Will allow the action to be placed in the body que accordingly.
* @param agreement - `optional` Is time in milliseconds of the actions intended lifetime.
* @param decisionNodes - `optional` The third or more option, may override success or failure in your workflows.
* @param preposition - `optional` String that prefixes the ActionType when added to the Strategy's ActionList.
Expand All @@ -35,6 +36,7 @@ export interface ActionNode {
actionType: ActionType;
payload?: Record<string, unknown>;
conceptSemaphore?: number;
priority?: number;
keyedSelectors?: KeyedSelector[];
semaphore?: [number, number, number, number];
agreement?: number;
Expand All @@ -53,6 +55,7 @@ export interface ActionNode {
* @param failureNode - `optional` ActionStrategy.failed() will fire Axium Conclude Type if left blank or set to null.
* @param semaphore - `optional` This will prime the action to avoid look up at run time. Best practice use getSemaphore().
* @param conceptSemaphore - `optional` Used for Unified Qualities. Must be specified via that principle's passed semaphore value.
* @param priority - `optional` Will allow the action to be placed in the body que accordingly.
* @param agreement - `optional` Is time in milliseconds of the actions intended lifetime.
* @param decisionNodes - `optional` The third or more option, may override success or failure in your workflows.
* @param preposition - `optional` String that prefixes the ActionType when added to the Strategy's ActionList.
Expand All @@ -64,6 +67,7 @@ export interface ActionNode {
export interface ActionNodeOptions {
keyedSelectors?: KeyedSelector[];
conceptSemaphore?: number;
priority?: number;
semaphore?: [number, number, number, number];
agreement?: number;
decisionNodes?: Record<string, ActionNode>;
Expand Down Expand Up @@ -97,6 +101,8 @@ export function createActionNode(action: Action, options?: ActionNodeOptions): A
actionType: action.type,
payload: action.payload,
keyedSelectors: action.keyedSelectors ? action.keyedSelectors : options.keyedSelectors,
conceptSemaphore: action.conceptSemaphore ? action.conceptSemaphore : options.conceptSemaphore,
priority: action.priority ? action.priority : options.priority,
agreement: action.agreement ? action.agreement : options.agreement,
semaphore: action.semaphore ? action.semaphore : options.semaphore,
successNode: options.successNode ? options.successNode : null,
Expand Down Expand Up @@ -133,7 +139,8 @@ export const createActionNodeFromStrategy = (strategy: ActionStrategy): ActionNo
currentNode.keyedSelectors,
currentNode.agreement,
currentNode.semaphore,
currentNode.conceptSemaphore
currentNode.conceptSemaphore,
currentNode.priority
);
}
return createActionNode(action, {
Expand Down
24 changes: 19 additions & 5 deletions src/model/axium.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {
Subscription,
Observer,
} from 'rxjs';
import { Action, createAction, createCacheSemaphores } from './action';
import { Action, createCacheSemaphores } from './action';
import { strategyBegin } from './actionStrategy';
import { Concept, Concepts, Mode, forEachConcept, qualityToString } from './concept';
import {
Expand All @@ -28,8 +28,9 @@ import { axiumPreClose } from '../concepts/axium/qualities/preClose.quality';
import { StagePlanner, Staging } from './stagePlanner';
import { axiumKick } from '../concepts/axium/qualities/kick.quality';
import { axiumTimeOut } from './time';
import { handlePriority, isPriorityValid } from './priority';

export const blockingMethodSubscription = (tail: Action[], action: Action) => {
export const blockingMethodSubscription = (concepts: Concepts, tail: Action[], action: Action) => {
if (
action.strategy &&
// Logical Determination: axiumConcludeType
Expand All @@ -42,7 +43,11 @@ export const blockingMethodSubscription = (tail: Action[], action: Action) => {
strategyData: action.strategy.data,
});
tail.push(appendToDialog);
tail.push(action);
if (isPriorityValid(action)) {
handlePriority(getAxiumState(concepts), action);
} else {
tail.push(action);
}
} else if (
action.strategy &&
// Logical Determination: axiumBadType
Expand All @@ -66,7 +71,11 @@ export const defaultMethodSubscription = (concepts: Concepts, tail: Action[], ac
});
// setTimeout(() => {
tail.push(appendToDialog);
tail.push(action);
if (isPriorityValid(action)) {
handlePriority(getAxiumState(concepts), action);
} else {
tail.push(action);
}
if (async) {
axiumTimeOut(concepts, () => {
return axiumKick();
Expand Down Expand Up @@ -115,7 +124,7 @@ export function createAxium(
}));
quality.toString = qualityToString(quality);
const methodSub = quality.method.subscribe(([action, _]) => {
blockingMethodSubscription(axiumState.tail, action);
blockingMethodSubscription(concepts, axiumState.tail, action);
}) as Subscriber<Action>;
axiumState = concepts[0].state as AxiumState;
axiumState.methodSubscribers.push({
Expand Down Expand Up @@ -150,6 +159,7 @@ export function createAxium(
.subscribe(([action, _concepts]: [Action, Concepts]) => {
// Would be notifying methods
const _axiumState = _concepts[0].state as AxiumState;
// console.log('CHECK QUES', _axiumState.head, _axiumState.body, _axiumState.tail);
if (_axiumState.head.length === 0) {
_axiumState.head.push(action);
if (_axiumState.tailTimer.length > 0) {
Expand Down Expand Up @@ -178,6 +188,10 @@ export function createAxium(
getAxiumState(concepts).action$.next(nextAction);
}
}
// An action dispatched from a priority stage, with a priority set to 0
// Will override the need to handle priority
} else if (isPriorityValid(action)) {
handlePriority(_axiumState, action);
} else {
_axiumState.body.push(action);
}
Expand Down
Loading
Loading