Extract timer handle runtime

master
dev 5 months ago
parent 34b682bab5
commit 59cccd55a6

@ -13,6 +13,7 @@ Estado al cierre:
- `arts/conn/connection.ts` delega auth/request/ACK request-reply en `connection-requests.ts`.
- `svrs/auth/adapters/memory-store.ts` queda como composition root de 39 lineas; la logica se reparte en stores internos de credentials, flows, linked accounts, sessions/devices, refresh y state/snapshot.
- `arts/perm/client.ts` delega transporte HTTP/JSON en `client-http.ts`; el cliente queda centrado en cache, snapshot y fallback.
- `arts/timr/engine-timers.ts` delega `TimerHandle` cancel/reschedule en `timer-handle.ts`.
- Integracion total ampliada: `Auth.signOut()` valida anonimizacion, invalidacion de `Permissions` y evento `Cache.invalidate`.
- Tanda focalizada verde: `npx vitest run src/arts/conn src/libs/cach src/arts/cach src/svrs/cach src/arts/auth src/svrs/auth src/libs/auth src/arts/aapp/test/ecosystem.integration.test.ts` -> 19 archivos, 82 tests.
- `/test/ecosystem` revisado en navegador: carga sin errores de consola, `ar` cambia a `rtl`, Formats se actualiza por locale, Perm cambia con rol `viewer`, Cach re-scopea por locale y Conn loopback publica/recibe.

@ -29,7 +29,6 @@ import {
ENGINE_METHOD_CANCEL_ALL,
ENGINE_METHOD_SCHEDULE,
ENGINE_METHOD_SCHEDULE_AT,
inactiveTimerErrorMessage,
TIMER_DIAGNOSTIC_EVENTS,
TIMER_EVENT_CANCELLED,
TIMER_EVENT_COMPLETED,
@ -46,12 +45,13 @@ import {
TIMER_STATUS_RUNNING
} from './consts.ts';
import { createTimerDiagnostics, emitTimerDiagnostic } from './diagnostics.ts';
import { TimrDuplicateKeyError, TimrInactiveTimerError } from './errors.ts';
import { TimrDuplicateKeyError } from './errors.ts';
import {
isTimerKeyInScope,
timerEntrySnapshot,
type InternalTimerEntry
} from './timer-entry.ts';
import { createTimerHandle } from './timer-handle.ts';
import {
assertTimerDelay,
assertTimerEngineLive,
@ -316,44 +316,15 @@ export function createEngineTimers(options: EngineTimersOptions = {}): EngineTim
}
function makeHandle(entry: InternalTimerEntry): TimerHandle {
const id = entry.id;
const key = entry.key;
return {
get key() {
return key;
},
get active() {
const live = entries.get(key);
return live !== undefined && live.id === id;
},
cancel() {
const live = entries.get(key);
if (live === undefined || live.id !== id) return false;
cancelEntry(live);
return true;
},
reschedule(delayMs: number) {
const live = entries.get(key);
if (live === undefined || live.id !== id) {
throw new TimrInactiveTimerError(inactiveTimerErrorMessage(key), key);
}
if (live.status === TIMER_STATUS_RUNNING) {
throw new TimrInactiveTimerError(inactiveTimerErrorMessage(key), key);
}
assertTimerDelay(delayMs);
if (live.native !== null) {
clock.clearTimeout(live.native);
live.native = null;
}
const now = clock.now();
live.scheduledAt = now;
live.delayMs = delayMs;
live.dueAt = now + delayMs;
live.status = TIMER_STATUS_PENDING;
armEntry(live, delayMs);
return createTimerHandle(entry, {
entries,
clock,
cancelEntry,
armEntry,
emitScheduled: (live) => {
emit({ type: TIMER_EVENT_SCHEDULED, entry: timerEntrySnapshot(live) });
}
};
});
}
// ── Public API ──────────────────────────────────────────────────────────

@ -0,0 +1,57 @@
import { inactiveTimerErrorMessage, TIMER_STATUS_PENDING, TIMER_STATUS_RUNNING } from './consts.ts';
import { TimrInactiveTimerError } from './errors.ts';
import type { InternalTimerEntry } from './timer-entry.ts';
import { assertTimerDelay } from './timer-validation.ts';
import type { TimerClock, TimerHandle } from './types.ts';
export interface TimerHandleRuntime {
readonly entries: Map<string, InternalTimerEntry>;
readonly clock: TimerClock;
cancelEntry(entry: InternalTimerEntry): void;
armEntry(entry: InternalTimerEntry, delayMs: number): void;
emitScheduled(entry: InternalTimerEntry): void;
}
export function createTimerHandle(
entry: InternalTimerEntry,
runtime: TimerHandleRuntime
): TimerHandle {
const id = entry.id;
const key = entry.key;
return {
get key() {
return key;
},
get active() {
const live = runtime.entries.get(key);
return live !== undefined && live.id === id;
},
cancel() {
const live = runtime.entries.get(key);
if (live === undefined || live.id !== id) return false;
runtime.cancelEntry(live);
return true;
},
reschedule(delayMs: number) {
const live = runtime.entries.get(key);
if (live === undefined || live.id !== id) {
throw new TimrInactiveTimerError(inactiveTimerErrorMessage(key), key);
}
if (live.status === TIMER_STATUS_RUNNING) {
throw new TimrInactiveTimerError(inactiveTimerErrorMessage(key), key);
}
assertTimerDelay(delayMs);
if (live.native !== null) {
runtime.clock.clearTimeout(live.native);
live.native = null;
}
const now = runtime.clock.now();
live.scheduledAt = now;
live.delayMs = delayMs;
live.dueAt = now + delayMs;
live.status = TIMER_STATUS_PENDING;
runtime.armEntry(live, delayMs);
runtime.emitScheduled(live);
}
};
}
Loading…
Cancel
Save

Powered by TurnKey Linux.