Skip to content

Commit

Permalink
changed: cont status
Browse files Browse the repository at this point in the history
  • Loading branch information
Viktor Pasynok committed Nov 3, 2024
1 parent f017a3f commit 8e3b50e
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 24 deletions.
36 changes: 18 additions & 18 deletions src/compose/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { combine, createEffect, createStore, launch, sample, type Store } from 'effector';
import { type AnyContainer } from '../createContainer';
import type { Status } from '../createContainer/types';
import { CONTAINER_STATUS, type ContainerStatus } from '../createContainer/types';

const validateContainerId = (id: string, set: Set<string>) => {
if (set.has(id)) {
Expand All @@ -9,10 +9,10 @@ const validateContainerId = (id: string, set: Set<string>) => {
set.add(id);
};

const READY_DEPS_LIST = [createStore<Status>('done')];
const READY_DEPS_LIST = [createStore<ContainerStatus>(CONTAINER_STATUS.done)];

// todo: tons of tests
// todo: simplify if (x.some((s) => s === 'off')) return 'off';
// todo: simplify if (x.some((s) => s === CONTAINER_STATUS.off)) return CONTAINER_STATUS.off;
// todo: clearNode extra stores and variables on container fail|off|done, and on all up
const upFn = (containers: AnyContainer[]) => {
const CONTAINER_IDS = new Set<string>();
Expand All @@ -24,40 +24,40 @@ const upFn = (containers: AnyContainer[]) => {
let apis: Record<string, Awaited<ReturnType<AnyContainer['start']>>['api']> = {};

for (const container of containers) {
const $strictDepsResolvingStatus: Store<Status> = combine(
const $strictDepsResolvingStatus: Store<ContainerStatus> = combine(
container.dependsOn ? container.dependsOn.map((d) => d.$status) : READY_DEPS_LIST,
(x) => {
if (x.some((s) => s === 'off')) return 'off';
if (x.some((s) => s === 'fail')) return 'fail';
if (x.some((s) => s === 'pending')) return 'pending';
if (x.some((s) => s === CONTAINER_STATUS.off)) return CONTAINER_STATUS.off;
if (x.some((s) => s === CONTAINER_STATUS.fail)) return CONTAINER_STATUS.fail;
if (x.some((s) => s === CONTAINER_STATUS.pending)) return CONTAINER_STATUS.pending;

if (x.every((s) => s === 'done')) return 'done';
if (x.every((s) => s === CONTAINER_STATUS.done)) return CONTAINER_STATUS.done;

return 'idle';
return CONTAINER_STATUS.idle;
},
);
const $optionalDepsResolvingStatus: Store<Status> = combine(
const $optionalDepsResolvingStatus: Store<ContainerStatus> = combine(
container.optionalDependsOn ? container.optionalDependsOn.map((d) => d.$status) : READY_DEPS_LIST,
(x) => {
if (x.some((s) => s === 'pending')) return 'pending';
if (x.some((s) => s === 'idle')) return 'idle';
if (x.some((s) => s === CONTAINER_STATUS.pending)) return CONTAINER_STATUS.pending;
if (x.some((s) => s === CONTAINER_STATUS.idle)) return CONTAINER_STATUS.idle;

return 'done';
return CONTAINER_STATUS.done;
},
);
const $depsReady = combine([$strictDepsResolvingStatus, $optionalDepsResolvingStatus], (s) =>
s.every((x) => x === 'done'),
s.every((x) => x === CONTAINER_STATUS.done),
);

const startFx = createEffect(async () => {
apis[container.id] = (await container.start(apis, apis))['api'];
});

sample({ clock: startFx.finally, fn: (x) => x.status, target: container.$status });
sample({ clock: container.$status, filter: (x) => x === 'pending', target: startFx });
sample({ clock: container.$status, filter: (x) => x === CONTAINER_STATUS.pending, target: startFx });

$strictDepsResolvingStatus.watch((s) => {
if (['off', 'fail'].includes(s)) {
if (s === CONTAINER_STATUS.off || s === CONTAINER_STATUS.fail) {
launch(container.$status, s);
}
});
Expand All @@ -67,9 +67,9 @@ const upFn = (containers: AnyContainer[]) => {
try {
const isEnabled = container.enable ? await container.enable(apis, apis) : true;

launch(container.$status, isEnabled ? 'pending' : 'off');
launch(container.$status, isEnabled ? CONTAINER_STATUS.pending : CONTAINER_STATUS.off);
} catch {
launch(container.$status, 'fail');
launch(container.$status, CONTAINER_STATUS.fail);
}
}
});
Expand Down
14 changes: 11 additions & 3 deletions src/createContainer/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
import { createStore } from 'effector';
import type { AnyAPI, AnyContainer, AnyDeps, EnableResult, StartResult, Status } from './types';
import { type ContainerIdEmptyStringError, validate } from './validate';
import {
CONTAINER_STATUS,
type AnyAPI,
type AnyContainer,
type AnyDeps,
type ContainerStatus,
type EnableResult,
type StartResult,
} from './types';
import { validate, type ContainerIdEmptyStringError } from './validate';

type ExtractDeps<D extends AnyContainer[]> = {
[K in D[number] as Awaited<ReturnType<K['start']>>['api'] extends Record<string, never> ? never : K['id']]: Awaited<
Expand Down Expand Up @@ -58,7 +66,7 @@ const createContainer = <
__params: Params<Id, API, Deps, OptionalDeps>,
) => {
const params = validate(__params);
const $status = createStore<Status>('idle');
const $status = createStore<ContainerStatus>(CONTAINER_STATUS.idle);

return {
...params,
Expand Down
16 changes: 13 additions & 3 deletions src/createContainer/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,17 @@ import { type StoreWritable } from 'effector';

type NonEmptyTuple<T = unknown> = [T, ...T[]];
type AnyObject = Record<string, unknown>;
type ValueOf<T> = T[keyof T];

type Status = 'idle' | 'pending' | 'done' | 'fail' | 'off';
const CONTAINER_STATUS = {
idle: 'idle',
pending: 'pending',
done: 'done',
fail: 'fail',
off: 'off',
} as const;

type ContainerStatus = ValueOf<typeof CONTAINER_STATUS>;
type StartResult<T> = Promise<{ api: T }> | { api: T };
type EnableResult = Promise<boolean> | boolean;

Expand All @@ -12,7 +21,7 @@ type AnyStartFn = (...x: any) => StartResult<AnyAPI>;

type AnyContainer = {
id: string;
$status: StoreWritable<Status>;
$status: StoreWritable<ContainerStatus>;
start: AnyStartFn;
dependsOn?: AnyContainer[];
optionalDependsOn?: AnyContainer[];
Expand All @@ -21,4 +30,5 @@ type AnyContainer = {

type AnyDeps = NonEmptyTuple<AnyContainer> | void;

export type { AnyAPI, AnyContainer, AnyDeps, EnableResult, StartResult, Status };
export { CONTAINER_STATUS };
export type { AnyAPI, AnyContainer, AnyDeps, ContainerStatus, EnableResult, StartResult };

0 comments on commit 8e3b50e

Please sign in to comment.