@atolis-hq/wake 0.3.43 → 0.3.45

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -49,6 +49,7 @@ function projectWork(view, event, occurredAt) {
49
49
  condition: BoardCondition.Ready,
50
50
  dwellSince: occurredAt,
51
51
  runCount: 0,
52
+ activeRuns: {},
52
53
  totalTokens: 0,
53
54
  inputTokens: 0,
54
55
  outputTokens: 0,
@@ -246,9 +247,11 @@ function projectRun(view, event, _occurredAt) {
246
247
  }
247
248
  function projectRunTerminal(view, event, workId, card) {
248
249
  const finishedAt = terminalFinishedAt(event);
249
- const runDurationMs = card.activeRun === undefined || finishedAt === undefined
250
+ const activeRuns = activeRunsFor(view, card, workId);
251
+ const activeRun = activeRuns[event.stream.id];
252
+ const runDurationMs = activeRun === undefined || finishedAt === undefined
250
253
  ? 0
251
- : Date.parse(finishedAt) - Date.parse(card.activeRun.startedAt);
254
+ : Date.parse(finishedAt) - Date.parse(activeRun.startedAt);
252
255
  const terminal = terminalRunFields(event);
253
256
  // Same legacy-checkpoint tolerance as the `children` guard above: a
254
257
  // checkpoint persisted before `childRuns` was added round-trips without
@@ -259,7 +262,8 @@ function projectRunTerminal(view, event, workId, card) {
259
262
  cards: {
260
263
  ...view.cards,
261
264
  [workId]: {
262
- ...withoutActiveRun(card),
265
+ ...withoutLegacyActiveRun(card),
266
+ activeRuns: withoutActiveRun(activeRuns, event.stream.id),
263
267
  ...(terminal === undefined ? {} : { lastRunOutcome: terminal.lastRunOutcome }),
264
268
  ...(terminal === undefined || isChildRun || terminal.condition === undefined
265
269
  ? {}
@@ -279,6 +283,7 @@ function projectRunStarted(view, event) {
279
283
  // that guard, so a checkpoint predating `children` must not crash here either.
280
284
  const childAction = view.children?.[event.payload.workflowInstanceId];
281
285
  const isChildRun = childAction !== undefined;
286
+ const activeRuns = activeRunsFor(view, card, workId);
282
287
  return {
283
288
  ...view,
284
289
  runs: { ...view.runs, [event.stream.id]: workId },
@@ -286,16 +291,21 @@ function projectRunStarted(view, event) {
286
291
  cards: {
287
292
  ...view.cards,
288
293
  [workId]: {
289
- ...(isChildRun ? card : withoutLastRunOutcome(withoutAwaitingApproval(card))),
294
+ ...(isChildRun
295
+ ? withoutLegacyActiveRun(card)
296
+ : withoutLegacyActiveRun(withoutLastRunOutcome(withoutAwaitingApproval(card)))),
290
297
  runCount: card.runCount + 1,
291
298
  ...(isChildRun ? {} : { condition: BoardCondition.Active }),
292
299
  lastRunAt: event.payload.startedAt,
293
- activeRun: {
294
- action: childAction ?? card.stage ?? event.payload.activity,
295
- startedAt: event.payload.startedAt,
296
- ...(event.payload.runner?.name === undefined
297
- ? {}
298
- : { runnerName: event.payload.runner.name }),
300
+ activeRuns: {
301
+ ...activeRuns,
302
+ [event.stream.id]: {
303
+ action: childAction ?? card.stage ?? event.payload.activity,
304
+ startedAt: event.payload.startedAt,
305
+ ...(event.payload.runner?.name === undefined
306
+ ? {}
307
+ : { runnerName: event.payload.runner.name }),
308
+ },
299
309
  },
300
310
  },
301
311
  },
@@ -327,7 +337,21 @@ function withoutAwaitingApproval(card) {
327
337
  const { awaitingApproval: _awaitingApproval, ...withoutApproval } = card;
328
338
  return withoutApproval;
329
339
  }
330
- function withoutActiveRun(card) {
340
+ function activeRunsFor(view, card, workId) {
341
+ if (card.activeRuns !== undefined)
342
+ return card.activeRuns;
343
+ if (card.activeRun === undefined)
344
+ return {};
345
+ const legacyRunId = Object.entries(view.runs)
346
+ .reverse()
347
+ .find(([, runWorkId]) => runWorkId === workId)?.[0];
348
+ return legacyRunId === undefined ? {} : { [legacyRunId]: card.activeRun };
349
+ }
350
+ function withoutActiveRun(activeRuns, runId) {
351
+ const { [runId]: _completed, ...remaining } = activeRuns;
352
+ return remaining;
353
+ }
354
+ function withoutLegacyActiveRun(card) {
331
355
  const { activeRun: _activeRun, ...withoutRun } = card;
332
356
  return withoutRun;
333
357
  }
@@ -29,39 +29,47 @@ function createBoardApplications(root, now) {
29
29
  async list(query) {
30
30
  const nowMs = Date.parse(now());
31
31
  const stored = await root.projections.read(boardProjection.name, 'global');
32
- const cards = Object.values(stored?.value.cards ?? {}).sort((left, right) => cardRecency(right).localeCompare(cardRecency(left)));
32
+ const board = stored?.value ?? boardProjection.initial('global');
33
+ const cards = Object.values(board.cards).sort((left, right) => cardRecency(right).localeCompare(cardRecency(left)));
33
34
  const offset = query.cursor?.position ?? 0;
34
35
  const page = cards.slice(offset, offset + query.limit);
35
36
  const items = await Promise.all(page.map(async (card) => {
36
37
  const externalRef = await primaryExternalRef(root, card.workItemId);
37
- const { activeRun, ...withoutActiveRun } = card;
38
+ const { activeRun: _legacyActiveRun, activeRuns: _activeRuns, ...withoutActiveRuns } = card;
39
+ const activeRuns = activeBoardRuns(board, card);
38
40
  return presentBoardCard({
39
- ...withoutActiveRun,
41
+ ...withoutActiveRuns,
40
42
  totalDurationMs: card.totalDurationMs ?? 0,
43
+ activeRuns: Object.fromEntries(Object.entries(activeRuns).map(([runId, activeRun]) => [
44
+ runId,
45
+ { ...activeRun, elapsedMs: elapsedSince(activeRun.startedAt, nowMs) },
46
+ ])),
41
47
  ...(externalRef === undefined ? {} : { externalRef }),
42
48
  ...(card.lastRunAt === undefined
43
49
  ? {}
44
50
  : { lastRunAgeMs: elapsedSince(card.lastRunAt, nowMs) }),
45
- ...(activeRun === undefined
46
- ? {}
47
- : {
48
- activeRun: {
49
- ...activeRun,
50
- elapsedMs: elapsedSince(activeRun.startedAt, nowMs),
51
- },
52
- }),
53
51
  });
54
52
  }));
55
53
  return {
56
54
  items,
57
55
  total: cards.length,
58
56
  ...(offset + query.limit < cards.length ? { nextPosition: offset + query.limit } : {}),
59
- conditionCounts: boardConditionCounts(stored?.value ?? boardProjection.initial('global')),
57
+ conditionCounts: boardConditionCounts(board),
60
58
  meta: await projectionMeta(root.journal, stored === null ? [] : [stored], now()),
61
59
  };
62
60
  },
63
61
  };
64
62
  }
63
+ function activeBoardRuns(board, card) {
64
+ if (card.activeRuns !== undefined)
65
+ return card.activeRuns;
66
+ if (card.activeRun === undefined)
67
+ return {};
68
+ const legacyRunId = Object.entries(board.runs)
69
+ .reverse()
70
+ .find(([, workItemId]) => workItemId === card.workItemId)?.[0];
71
+ return legacyRunId === undefined ? {} : { [legacyRunId]: card.activeRun };
72
+ }
65
73
  function createStatusApplications(root, now) {
66
74
  return {
67
75
  async get() {
@@ -108,4 +108,4 @@ export function resolveWakeVersion(options = {}) {
108
108
  return `g${headHash.slice(0, 7)}`;
109
109
  return '0.1.0-dev';
110
110
  }
111
- export const wakeVersion = "g7b49dab";
111
+ export const wakeVersion = "g8f84f8d";
@@ -15,6 +15,16 @@ export async function acquireFileLock(path, options) {
15
15
  : acquireLegacyFileLock(path, metadata, options);
16
16
  }
17
17
  async function acquireStrictFileLock(path, metadata, options) {
18
+ try {
19
+ return await acquireStrictFileLockOnce(path, metadata, options);
20
+ }
21
+ catch (error) {
22
+ if (error.code !== 'ENOENT')
23
+ throw error;
24
+ return acquireStrictFileLockOnce(path, metadata, options);
25
+ }
26
+ }
27
+ async function acquireStrictFileLockOnce(path, metadata, options) {
18
28
  const ownersPath = `${path}.owners`;
19
29
  await mkdir(ownersPath, { recursive: true });
20
30
  const legacy = await inspectLegacyOwner(path, ownersPath, options);