@medamajs/compose
Version:
Composable state management extension for medama with support for hierarchical state layers, dynamic composition, and parallel state synchronization
249 lines (206 loc) • 7.02 kB
text/typescript
import { createMedama } from 'medama';
/**
* Function to execute job with read mode enabled. Sets read work state to true
* before execution, resets both read work and subscription means states after
* completion.
*
* @param job Function to execute in read mode
*/
type RunWithReadModeOn = (job: () => void) => void;
type ReadWorkModeMethods = {
/**
* Returns current read work state. True indicates that reading process is in
* progress and any nested reads should be treated as derivative calls rather
* than initiator calls.
*/
getReadWorkState: () => boolean;
/**
* Function to execute job with read mode enabled. Sets read work state to
* true before execution, resets both read work and subscription means states
* after completion.
*/
runWithReadModeOn: RunWithReadModeOn;
/**
* Sets subscription means requested state to true. Indicates that nested
* composite states should collect and relay subscription means up the chain.
*/
setSubscriptionMeansRequested: () => void;
/**
* Returns current subscription means requested state. True indicates that
* nested composite states should collect and relay subscription means up the
* chain.
*/
getRequestSubscriptionMeansState: () => boolean;
/**
* Resets both read work state and subscription means requested state to
* false. Used during initialization and error handling to ensure clean state.
*/
resetReadWorkMode: () => void;
};
/**
* Creates a manager to control read work mode and subscription collection
* state. Manages two key states:
* - Read work state: Tracks if reading process is active
* - Subscription means state: Controls if nested states should collect
* subscriptions
*
* Provides methods to:
* - Start/finish reading operations
* - Control subscription means collection
* - Reset states during initialization or error handling
*
* @returns Object containing methods to manage read work mode
*/
export const createReadWorkModeManager = (): ReadWorkModeMethods => {
let readWorkState = false;
let requestSubscriptionMeansState = false;
const getReadWorkState = (): boolean => readWorkState;
const runWithReadModeOn = (job: () => void): void => {
readWorkState = true;
job();
readWorkState = false;
requestSubscriptionMeansState = false;
};
const setSubscriptionMeansRequested = (): void => {
requestSubscriptionMeansState = true;
};
const getRequestSubscriptionMeansState = (): boolean => requestSubscriptionMeansState;
const resetReadWorkMode = (): void => {
readWorkState = false;
requestSubscriptionMeansState = false;
};
return {
getReadWorkState,
runWithReadModeOn,
setSubscriptionMeansRequested,
getRequestSubscriptionMeansState,
resetReadWorkMode,
};
};
export type DeferOrRun = (job: () => void) => void;
type Reset = () => void;
type ConditionalDeferrerMethods = {
/**
* Either runs job immediately or defers it based on update work state:
* - If not in update mode: runs job immediately
* - If in update mode: defers job and subscribes to resolution signal (if not
* already subscribed)
*/
deferOrRun: DeferOrRun;
/**
* Resets subscription state to false. Used during initialization and error
* handling to ensure clean state.
*/
reset: Reset;
};
type CreateConditionalDeferrer = (
deferJob: (job: () => void) => void,
resolveDeferred: () => void
) => ConditionalDeferrerMethods;
type UpdateWorkModeMethods = {
/**
* Returns current update work state. True indicates that update process is in
* progress and new jobs should be deferred rather than executed immediately.
*/
getUpdateWorkState: () => boolean;
/**
* Sets update work state to true, indicating start of update process. Used to
* mark that any new jobs should be deferred rather than executed immediately.
*/
startUpdating: () => void;
/**
* Signals resolution of deferred jobs and sets update work state to false.
* Triggers execution of all deferred jobs in the queue.
*/
signalDeferredJobsToResolve: () => void;
/**
* Creates a handler that either runs jobs immediately or defers them based on
* current state. Provides subscription mechanism to resolve deferred jobs
* when signaled.
*
* @param deferJob Function to add job to deferred queue
* @param resolveDeferred Function to process deferred queue
*/
createConditionalDeferrer: CreateConditionalDeferrer;
/**
* Resets signal state and update work state to false. Used during
* initialization and error handling to ensure clean state.
*/
resetUpdateWorkMode: () => void;
};
type SignalToResolveDeferredJobsState = {
signal: object;
};
/**
* Creates a manager to control update work mode and deferred job handling.
* Manages update state and provides mechanisms for:
* - Controlling when jobs should be deferred vs executed immediately
* - Signaling when deferred jobs should be processed
* - Creating conditional deferrer instances that handle job execution timing
*
* Uses medama state to manage signaling system for deferred job resolution.
*
* @returns Object containing methods to manage update work mode and job
* deferral
*/
export const createUpdateWorkModeManager = (): UpdateWorkModeMethods => {
let updateWorkState = false;
const getUpdateWorkState = (): boolean => updateWorkState;
const startUpdating = (): void => {
updateWorkState = true;
};
const {
subscribeToState: subscribeToSignalState,
setState: setSignalState,
resetState: resetSignalState,
} = createMedama<SignalToResolveDeferredJobsState>();
const signalToResolveSelector = ({ signal }: SignalToResolveDeferredJobsState): object => signal;
const signalDeferredJobsToResolve = (): void => {
setSignalState({ signal: {} });
updateWorkState = false;
};
const subscribeForResolvingWhenSignalled = (callback: () => void): void => {
const { unsubscribe } = subscribeToSignalState(
signalToResolveSelector,
(): (() => void) => () => {
callback();
unsubscribe();
}
);
};
const createConditionalDeferrer = (
deferJob: (job: () => void) => void,
resolveDeferred: () => void
): ConditionalDeferrerMethods => {
let subscribed = false;
return {
deferOrRun: (job): void => {
if (updateWorkState === false) {
job();
return;
}
deferJob(job);
if (subscribed) return;
subscribeForResolvingWhenSignalled((): void => {
resolveDeferred();
subscribed = false;
});
subscribed = true;
},
reset: (): void => {
subscribed = false;
},
};
};
const resetUpdateWorkMode = (): void => {
resetSignalState();
updateWorkState = false;
};
return {
getUpdateWorkState,
startUpdating,
signalDeferredJobsToResolve,
createConditionalDeferrer,
resetUpdateWorkMode,
};
};