@usine/orchestrator 0.2.1 → 0.3.0

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.
Files changed (173) hide show
  1. package/README.md +151 -52
  2. package/dist/board/items.d.ts +9 -1
  3. package/dist/board/items.d.ts.map +1 -1
  4. package/dist/board/items.js +16 -4
  5. package/dist/board/items.js.map +1 -1
  6. package/dist/board/projection.d.ts +7 -1
  7. package/dist/board/projection.d.ts.map +1 -1
  8. package/dist/board/projection.js +53 -14
  9. package/dist/board/projection.js.map +1 -1
  10. package/dist/board/tasks.d.ts +14 -2
  11. package/dist/board/tasks.d.ts.map +1 -1
  12. package/dist/board/tasks.js +23 -8
  13. package/dist/board/tasks.js.map +1 -1
  14. package/dist/credentials.d.ts +5 -6
  15. package/dist/credentials.d.ts.map +1 -1
  16. package/dist/credentials.js +22 -15
  17. package/dist/credentials.js.map +1 -1
  18. package/dist/current-instance/changes.d.ts +87 -0
  19. package/dist/current-instance/changes.d.ts.map +1 -0
  20. package/dist/current-instance/changes.js +138 -0
  21. package/dist/current-instance/changes.js.map +1 -0
  22. package/dist/current-instance/current-instance.d.ts +89 -0
  23. package/dist/current-instance/current-instance.d.ts.map +1 -0
  24. package/dist/current-instance/current-instance.js +163 -0
  25. package/dist/current-instance/current-instance.js.map +1 -0
  26. package/dist/exe-dev.d.ts +6 -2
  27. package/dist/exe-dev.d.ts.map +1 -1
  28. package/dist/exe-dev.js +7 -8
  29. package/dist/exe-dev.js.map +1 -1
  30. package/dist/idle-triggers.d.ts +1 -1
  31. package/dist/idle-triggers.d.ts.map +1 -1
  32. package/dist/idle-triggers.js +1 -1
  33. package/dist/idle-triggers.js.map +1 -1
  34. package/dist/label-reconciler.d.ts +5 -2
  35. package/dist/label-reconciler.d.ts.map +1 -1
  36. package/dist/label-reconciler.js.map +1 -1
  37. package/dist/local.d.ts +4 -18
  38. package/dist/local.d.ts.map +1 -1
  39. package/dist/local.js +7 -45
  40. package/dist/local.js.map +1 -1
  41. package/dist/loop-matches.d.ts +28 -0
  42. package/dist/loop-matches.d.ts.map +1 -0
  43. package/dist/loop-matches.js +74 -0
  44. package/dist/loop-matches.js.map +1 -0
  45. package/dist/operator/attempt.d.ts +57 -10
  46. package/dist/operator/attempt.d.ts.map +1 -1
  47. package/dist/operator/attempt.js +49 -10
  48. package/dist/operator/attempt.js.map +1 -1
  49. package/dist/operator/board.d.ts +43 -16
  50. package/dist/operator/board.d.ts.map +1 -1
  51. package/dist/operator/board.js +43 -16
  52. package/dist/operator/board.js.map +1 -1
  53. package/dist/operator/configuration.d.ts +258 -0
  54. package/dist/operator/configuration.d.ts.map +1 -0
  55. package/dist/operator/configuration.js +410 -0
  56. package/dist/operator/configuration.js.map +1 -0
  57. package/dist/operator/desk.d.ts +181 -0
  58. package/dist/operator/desk.d.ts.map +1 -0
  59. package/dist/operator/desk.js +463 -0
  60. package/dist/operator/desk.js.map +1 -0
  61. package/dist/operator/github-changes.d.ts +88 -0
  62. package/dist/operator/github-changes.d.ts.map +1 -0
  63. package/dist/operator/github-changes.js +266 -0
  64. package/dist/operator/github-changes.js.map +1 -0
  65. package/dist/operator/http.d.ts +152 -57
  66. package/dist/operator/http.d.ts.map +1 -1
  67. package/dist/operator/http.js +140 -21
  68. package/dist/operator/http.js.map +1 -1
  69. package/dist/operator/need.d.ts +44 -11
  70. package/dist/operator/need.d.ts.map +1 -1
  71. package/dist/operator/need.js +46 -9
  72. package/dist/operator/need.js.map +1 -1
  73. package/dist/operator/operator.d.ts +109 -29
  74. package/dist/operator/operator.d.ts.map +1 -1
  75. package/dist/operator/operator.js +254 -52
  76. package/dist/operator/operator.js.map +1 -1
  77. package/dist/operator/overview.d.ts +7 -7
  78. package/dist/operator/overview.d.ts.map +1 -1
  79. package/dist/operator/overview.js +5 -5
  80. package/dist/operator/overview.js.map +1 -1
  81. package/dist/operator/projection.d.ts +54 -5
  82. package/dist/operator/projection.d.ts.map +1 -1
  83. package/dist/operator/projection.js +100 -9
  84. package/dist/operator/projection.js.map +1 -1
  85. package/dist/operator/run.d.ts +71 -6
  86. package/dist/operator/run.d.ts.map +1 -1
  87. package/dist/operator/run.js +69 -6
  88. package/dist/operator/run.js.map +1 -1
  89. package/dist/operator/task.d.ts +93 -0
  90. package/dist/operator/task.d.ts.map +1 -0
  91. package/dist/operator/task.js +204 -0
  92. package/dist/operator/task.js.map +1 -0
  93. package/dist/operator/transcript.d.ts +12 -12
  94. package/dist/operator/transcript.d.ts.map +1 -1
  95. package/dist/operator/transcript.js +11 -9
  96. package/dist/operator/transcript.js.map +1 -1
  97. package/dist/operator/usage.d.ts +111 -0
  98. package/dist/operator/usage.d.ts.map +1 -0
  99. package/dist/operator/usage.js +219 -0
  100. package/dist/operator/usage.js.map +1 -0
  101. package/dist/orchestrator.d.ts +8 -5
  102. package/dist/orchestrator.d.ts.map +1 -1
  103. package/dist/orchestrator.js +4 -2
  104. package/dist/orchestrator.js.map +1 -1
  105. package/dist/polling/cycle.d.ts +28 -10
  106. package/dist/polling/cycle.d.ts.map +1 -1
  107. package/dist/polling/cycle.js +20 -6
  108. package/dist/polling/cycle.js.map +1 -1
  109. package/dist/polling/evaluation-failures.d.ts +42 -0
  110. package/dist/polling/evaluation-failures.d.ts.map +1 -0
  111. package/dist/polling/evaluation-failures.js +103 -0
  112. package/dist/polling/evaluation-failures.js.map +1 -0
  113. package/dist/polling/hints.d.ts +2 -2
  114. package/dist/polling/hints.d.ts.map +1 -1
  115. package/dist/polling/hints.js +2 -2
  116. package/dist/polling/hints.js.map +1 -1
  117. package/dist/polling/loop-evaluation.d.ts +21 -11
  118. package/dist/polling/loop-evaluation.d.ts.map +1 -1
  119. package/dist/polling/loop-evaluation.js +70 -27
  120. package/dist/polling/loop-evaluation.js.map +1 -1
  121. package/dist/polling/open-issues.d.ts +23 -0
  122. package/dist/polling/open-issues.d.ts.map +1 -0
  123. package/dist/polling/open-issues.js +77 -0
  124. package/dist/polling/open-issues.js.map +1 -0
  125. package/dist/polling/polling.d.ts +20 -11
  126. package/dist/polling/polling.d.ts.map +1 -1
  127. package/dist/polling/polling.js +201 -51
  128. package/dist/polling/polling.js.map +1 -1
  129. package/dist/polling/repository-sync.d.ts +20 -14
  130. package/dist/polling/repository-sync.d.ts.map +1 -1
  131. package/dist/polling/repository-sync.js +34 -27
  132. package/dist/polling/repository-sync.js.map +1 -1
  133. package/dist/polling-triggers.d.ts +1 -1
  134. package/dist/polling-triggers.d.ts.map +1 -1
  135. package/dist/polling-triggers.js +1 -1
  136. package/dist/polling-triggers.js.map +1 -1
  137. package/dist/reloads.d.ts +14 -0
  138. package/dist/reloads.d.ts.map +1 -0
  139. package/dist/reloads.js +7 -0
  140. package/dist/reloads.js.map +1 -0
  141. package/dist/runtime.d.ts +24 -0
  142. package/dist/runtime.d.ts.map +1 -0
  143. package/dist/runtime.js +58 -0
  144. package/dist/runtime.js.map +1 -0
  145. package/dist/schedule-triggers.d.ts +14 -10
  146. package/dist/schedule-triggers.d.ts.map +1 -1
  147. package/dist/schedule-triggers.js +36 -31
  148. package/dist/schedule-triggers.js.map +1 -1
  149. package/dist/scheduler.d.ts +35 -4
  150. package/dist/scheduler.d.ts.map +1 -1
  151. package/dist/scheduler.js +327 -41
  152. package/dist/scheduler.js.map +1 -1
  153. package/dist/ssh.d.ts +39 -0
  154. package/dist/ssh.d.ts.map +1 -0
  155. package/dist/ssh.js +75 -0
  156. package/dist/ssh.js.map +1 -0
  157. package/dist/trigger-condition.d.ts +12 -0
  158. package/dist/trigger-condition.d.ts.map +1 -0
  159. package/dist/trigger-condition.js +88 -0
  160. package/dist/trigger-condition.js.map +1 -0
  161. package/dist/trigger-submission.d.ts +16 -13
  162. package/dist/trigger-submission.d.ts.map +1 -1
  163. package/dist/trigger-submission.js +19 -14
  164. package/dist/trigger-submission.js.map +1 -1
  165. package/dist/worker-engine.d.ts +10 -0
  166. package/dist/worker-engine.d.ts.map +1 -0
  167. package/dist/worker-engine.js +25 -0
  168. package/dist/worker-engine.js.map +1 -0
  169. package/dist/worker-status.d.ts +70 -0
  170. package/dist/worker-status.d.ts.map +1 -0
  171. package/dist/worker-status.js +55 -0
  172. package/dist/worker-status.js.map +1 -0
  173. package/package.json +31 -10
@@ -1 +1 @@
1
- {"version":3,"file":"loop-evaluation.js","sourceRoot":"","sources":["../../src/polling/loop-evaluation.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"loop-evaluation.js","sourceRoot":"","sources":["../../src/polling/loop-evaluation.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ import type { ManagedRepo } from "@usine/config/factory";
2
+ import { ItemProjectionReader } from "@usine/engine/item-projection";
3
+ import { GitHubPolling } from "@usine/github/polling";
4
+ import { DateTime, Duration, Effect, Option } from "effect";
5
+ import type { ResolvedLoop } from "../trigger-submission.ts";
6
+ import { RepositoryPollFailure } from "./cycle.ts";
7
+ /** The minimum time between open issue checks of a repository. */
8
+ export declare const OPEN_ISSUE_CHECK_INTERVAL: Duration.Duration;
9
+ /** The result of one open issue check in a poll cycle. */
10
+ interface OpenIssueCheck {
11
+ readonly revokedRuns: number;
12
+ readonly failures: ReadonlyArray<RepositoryPollFailure>;
13
+ readonly nextPollAt: Option.Option<DateTime.Utc>;
14
+ }
15
+ export declare const NO_OPEN_ISSUE_CHECK: OpenIssueCheck;
16
+ /**
17
+ * Marks each issue stored as open in `repository` that GitHub no longer has as gone, and revokes
18
+ * its unstarted Runs. Reports GitHub request failures without failing the cycle; fails on
19
+ * persistence errors.
20
+ */
21
+ export declare const checkOpenIssues: (repository: ManagedRepo, loops: readonly ResolvedLoop[]) => Effect.Effect<OpenIssueCheck, import("@usine/engine/engine").AttemptCancellationError | import("@usine/engine/engine").EnginePersistenceError | import("@usine/engine/engine").RunInterventionRejectedError | import("@usine/engine/engine").RunNotFoundError | import("@usine/engine/engine").RunOperationRejectedError | import("@usine/engine/engine").RunRetryBlockedError, GitHubPolling | ItemProjectionReader | import("@usine/engine/item-projection").ItemProjectionWriter | import("@usine/engine/engine").RunEngine>;
22
+ export {};
23
+ //# sourceMappingURL=open-issues.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"open-issues.d.ts","sourceRoot":"","sources":["../../src/polling/open-issues.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AACrE,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AACtD,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAU,MAAM,QAAQ,CAAC;AACpE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,EAAE,qBAAqB,EAA8B,MAAM,YAAY,CAAC;AAI/E,kEAAkE;AAClE,eAAO,MAAM,yBAAyB,mBAAuB,CAAC;AAE9D,0DAA0D;AAC1D,UAAU,cAAc;IACtB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,QAAQ,EAAE,aAAa,CAAC,qBAAqB,CAAC,CAAC;IACxD,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;CAClD;AAED,eAAO,MAAM,mBAAmB,EAAE,cAIjC,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,eAAe,8jBA4D1B,CAAC"}
@@ -0,0 +1,77 @@
1
+ import { ItemProjectionReader } from "@usine/engine/item-projection";
2
+ import { GitHubPolling } from "@usine/github/polling";
3
+ import { DateTime, Duration, Effect, Option, Result } from "effect";
4
+ import { RepositoryPollFailure, repositoryFailureLogFields } from "./cycle.js";
5
+ import { revokeMissingItem } from "./loop-evaluation.js";
6
+ import { markItemGone } from "./repository-sync.js";
7
+ /** The minimum time between open issue checks of a repository. */
8
+ export const OPEN_ISSUE_CHECK_INTERVAL = Duration.minutes(10);
9
+ export const NO_OPEN_ISSUE_CHECK = {
10
+ revokedRuns: 0,
11
+ failures: [],
12
+ nextPollAt: Option.none(),
13
+ };
14
+ /**
15
+ * Marks each issue stored as open in `repository` that GitHub no longer has as gone, and revokes
16
+ * its unstarted Runs. Reports GitHub request failures without failing the cycle; fails on
17
+ * persistence errors.
18
+ */
19
+ export const checkOpenIssues = Effect.fn("PollingTriggers.checkOpenIssues")(function* (repository, loops) {
20
+ yield* Effect.annotateCurrentSpan({ repository: repository.name });
21
+ const items = yield* ItemProjectionReader;
22
+ const github = yield* GitHubPolling;
23
+ const open = yield* items.openIssues(repository.name);
24
+ if (open.length === 0) {
25
+ yield* Effect.logDebug("No open issues to check against GitHub", {
26
+ repository: repository.name,
27
+ });
28
+ return NO_OPEN_ISSUE_CHECK;
29
+ }
30
+ const result = yield* Effect.result(github.missingIssues(repository.name, open));
31
+ if (Result.isFailure(result)) {
32
+ const error = result.failure;
33
+ if (error._tag === "GitHubRateLimitError") {
34
+ yield* Effect.logWarning("Open-issue check rate-limited; checking again in 10 minutes", {
35
+ repository: repository.name,
36
+ openIssues: open.length,
37
+ operation: error.operation,
38
+ retryAt: DateTime.formatIso(error.retryAt),
39
+ });
40
+ return { ...NO_OPEN_ISSUE_CHECK, nextPollAt: Option.some(error.retryAt) };
41
+ }
42
+ yield* Effect.logError("Open-issue check failed; checking again in 10 minutes", {
43
+ repository: repository.name,
44
+ openIssues: open.length,
45
+ ...repositoryFailureLogFields(error),
46
+ });
47
+ return {
48
+ ...NO_OPEN_ISSUE_CHECK,
49
+ failures: [
50
+ new RepositoryPollFailure({
51
+ repository: repository.name,
52
+ errorTag: error._tag,
53
+ message: error.message,
54
+ }),
55
+ ],
56
+ };
57
+ }
58
+ let revokedRuns = 0;
59
+ for (const number of result.success) {
60
+ const revoked = yield* revokeMissingItem(repository, loops, "issue", number);
61
+ const projectionMarkedGone = yield* markItemGone(repository.name, number);
62
+ revokedRuns += revoked;
63
+ yield* Effect.logInfo("GitHub no longer has an open issue; it leaves the open lanes", {
64
+ repository: repository.name,
65
+ item: number,
66
+ revokedRuns: revoked,
67
+ projectionMarkedGone,
68
+ });
69
+ }
70
+ yield* Effect.logDebug("Checked open issues against GitHub", {
71
+ repository: repository.name,
72
+ openIssues: open.length,
73
+ missingIssues: result.success.length,
74
+ });
75
+ return { ...NO_OPEN_ISSUE_CHECK, revokedRuns };
76
+ });
77
+ //# sourceMappingURL=open-issues.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"open-issues.js","sourceRoot":"","sources":["../../src/polling/open-issues.ts"],"names":[],"mappings":"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"}
@@ -4,33 +4,42 @@ import { type RepositoryName } from "@usine/core/repository";
4
4
  import { CursorStore } from "@usine/engine/cursor";
5
5
  import { CycleBudgets } from "@usine/engine/cycle-budget";
6
6
  import { RunEngine, type EnginePersistenceError } from "@usine/engine/engine";
7
- import { ItemProjectionWriter } from "@usine/engine/item-projection";
7
+ import { ItemProjectionReader, ItemProjectionWriter } from "@usine/engine/item-projection";
8
8
  import { LoopControl } from "@usine/engine/loop-control";
9
9
  import { RepositoryLabelProjectionReader, RepositoryLabelProjectionWriter } from "@usine/engine/repository-label-projection";
10
10
  import { ExpressionEngine } from "@usine/expression/expression-engine";
11
11
  import { type ChangedItem, GitHubPolling } from "@usine/github/polling";
12
12
  import { Context, DateTime, Effect, Layer, Option } from "effect";
13
13
  import { LabelReconciler } from "../label-reconciler.ts";
14
+ import { type WatchedInstance } from "../reloads.ts";
14
15
  import { PollCycle } from "./cycle.ts";
15
16
  declare const PollingTriggers_base: Context.ServiceClass<PollingTriggers, "@usine/orchestrator/PollingTriggers", {
16
17
  /**
17
- * Polls every managed repository, including those without active Loops.
18
- * Label preflight precedes change detection; each changed Item is projected
19
- * before its Run decisions. A repository commits its cursor only after all
20
- * Items finish. Repository failures are reported while siblings continue;
21
- * failure to read Loop runtime state fails the whole cycle.
18
+ * Polls every managed repository and evaluates its Loops against changed Items. Reports
19
+ * repository failures without stopping the others; fails only if Loop runtime state can't be
20
+ * read.
22
21
  */
23
22
  readonly poll: (instance: LoadedInstance) => Effect.Effect<PollCycle, EnginePersistenceError>;
24
- /** Nudges an authoritative Item fetch after a self-write, retaining any request backoff from the writer. Pending duplicates coalesce; polling repairs loss. */
23
+ /**
24
+ * Requests an Item fetch after a self-write, keeping the writer's request backoff. Duplicate
25
+ * hints coalesce, and polling repairs lost ones.
26
+ */
25
27
  readonly hint: (repository: RepositoryName, item: ChangedItem, backoffUntil?: Option.Option<DateTime.Utc>) => Effect.Effect<void>;
26
- /** Repeats cycles at the configured interval and processes self-write Hints, respecting GitHub request backoff. */
27
- readonly run: (instance: LoadedInstance) => Effect.Effect<never>;
28
- /** The last completed cycle, including its isolated failures; absent until the first cycle completes. */
28
+ /**
29
+ * Runs cycles at the configured interval and processes self-write hints, respecting GitHub
30
+ * request backoff. An accepted reload starts the next cycle immediately, unless GitHub asked to
31
+ * wait longer.
32
+ */
33
+ readonly run: (instances: WatchedInstance) => Effect.Effect<never>;
34
+ /**
35
+ * The last completed cycle with its isolated failures, or `None` before the first cycle
36
+ * completes.
37
+ */
29
38
  readonly latest: Effect.Effect<Option.Option<PollCycle>>;
30
39
  }>;
31
40
  /** Keeps managed repositories' Boards current and evaluates their active Loops against changed Items. */
32
41
  export declare class PollingTriggers extends PollingTriggers_base {
33
- static readonly layer: Layer.Layer<PollingTriggers, never, ConfigParser | CursorStore | CycleBudgets | ExpressionEngine | GitHubPolling | ItemProjectionWriter | LabelReconciler | LoopControl | RepositoryLabelProjectionReader | RepositoryLabelProjectionWriter | RunEngine>;
42
+ static readonly layer: Layer.Layer<PollingTriggers, never, ConfigParser | CursorStore | CycleBudgets | ExpressionEngine | GitHubPolling | ItemProjectionReader | ItemProjectionWriter | LabelReconciler | LoopControl | RepositoryLabelProjectionReader | RepositoryLabelProjectionWriter | RunEngine>;
34
43
  }
35
44
  export {};
36
45
  //# sourceMappingURL=polling.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"polling.d.ts","sourceRoot":"","sources":["../../src/polling/polling.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAE7D,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAEpD,OAAO,EAA2B,KAAK,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACtF,OAAO,EAAa,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC1D,OAAO,EACL,SAAS,EACT,KAAK,sBAAsB,EAE5B,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AACrE,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AACzD,OAAO,EACL,+BAA+B,EAC/B,+BAA+B,EAChC,MAAM,2CAA2C,CAAC;AACnD,OAAO,EAAE,gBAAgB,EAAE,MAAM,qCAAqC,CAAC;AACvE,OAAO,EAAE,KAAK,WAAW,EAAyB,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAC/F,OAAO,EAEL,OAAO,EACP,QAAQ,EAER,MAAM,EACN,KAAK,EACL,MAAM,EAKP,MAAM,QAAQ,CAAC;AAChB,OAAO,EAAE,eAAe,EAA8B,MAAM,wBAAwB,CAAC;AAErF,OAAO,EAGL,SAAS,EAIV,MAAM,YAAY,CAAC;;IAmEhB;;;;;;OAMG;mBACY,CAAC,QAAQ,EAAE,cAAc,KAAK,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,sBAAsB,CAAC;IAC7F,+JAA+J;mBAChJ,CACb,UAAU,EAAE,cAAc,EAC1B,IAAI,EAAE,WAAW,EACjB,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,KACvC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC;IACxB,mHAAmH;kBACrG,CAAC,QAAQ,EAAE,cAAc,KAAK,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC;IAChE,yGAAyG;qBACxF,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;;AArB5D,yGAAyG;AACzG,qBAAa,eAAgB,SAAQ,oBAsBK;IACxC,MAAM,CAAC,QAAQ,CAAC,KAAK,2PAyVkB;CACxC"}
1
+ {"version":3,"file":"polling.d.ts","sourceRoot":"","sources":["../../src/polling/polling.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAE7D,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAEpD,OAAO,EAA2B,KAAK,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACtF,OAAO,EAAa,WAAW,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC1D,OAAO,EACL,SAAS,EACT,KAAK,sBAAsB,EAE5B,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AAC3F,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AACzD,OAAO,EACL,+BAA+B,EAC/B,+BAA+B,EAChC,MAAM,2CAA2C,CAAC;AACnD,OAAO,EAAE,gBAAgB,EAAE,MAAM,qCAAqC,CAAC;AACvE,OAAO,EAEL,KAAK,WAAW,EAGhB,aAAa,EACd,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAEL,OAAO,EACP,QAAQ,EAER,MAAM,EACN,KAAK,EACL,MAAM,EAKP,MAAM,QAAQ,CAAC;AAChB,OAAO,EAAE,eAAe,EAA8B,MAAM,wBAAwB,CAAC;AACrF,OAAO,EAAgB,KAAK,eAAe,EAAE,MAAM,eAAe,CAAC;AAEnE,OAAO,EAGL,SAAS,EAKV,MAAM,YAAY,CAAC;;IA8FhB;;;;OAIG;mBACY,CAAC,QAAQ,EAAE,cAAc,KAAK,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,sBAAsB,CAAC;IAC7F;;;OAGG;mBACY,CACb,UAAU,EAAE,cAAc,EAC1B,IAAI,EAAE,WAAW,EACjB,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,KACvC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC;IACxB;;;;OAIG;kBACW,CAAC,SAAS,EAAE,eAAe,KAAK,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC;IAClE;;;OAGG;qBACc,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;;AA7B5D,yGAAyG;AACzG,qBAAa,eAAgB,SAAQ,oBA8BK;IACxC,MAAM,CAAC,QAAQ,CAAC,KAAK,kRAmjBkB;CACxC"}
@@ -4,27 +4,35 @@ import { canonicalRepositoryName } from "@usine/core/repository";
4
4
  import { CursorKey, CursorStore } from "@usine/engine/cursor";
5
5
  import { CycleBudgets } from "@usine/engine/cycle-budget";
6
6
  import { RunEngine, } from "@usine/engine/engine";
7
- import { ItemProjectionWriter } from "@usine/engine/item-projection";
7
+ import { ItemProjectionReader, ItemProjectionWriter } from "@usine/engine/item-projection";
8
8
  import { LoopControl } from "@usine/engine/loop-control";
9
9
  import { RepositoryLabelProjectionReader, RepositoryLabelProjectionWriter, } from "@usine/engine/repository-label-projection";
10
10
  import { ExpressionEngine } from "@usine/expression/expression-engine";
11
- import { EntityTag, PollCursor, GitHubPolling } from "@usine/github/polling";
11
+ import { ChangedPullRequest, EntityTag, PollCursor, GitHubPolling, } from "@usine/github/polling";
12
12
  import { Clock, Context, DateTime, Duration, Effect, Layer, Option, Ref, Result, Schema, Semaphore, } from "effect";
13
13
  import { LabelReconciler } from "../label-reconciler.js";
14
+ import { reloadedFrom } from "../reloads.js";
14
15
  import { resolveTriggerLoops } from "../trigger-submission.js";
15
- import { latestPollAt, PollCycle, RepositoryPollFailure, repositoryFailureLogFields, } from "./cycle.js";
16
- import { evaluateItem } from "./loop-evaluation.js";
17
- import { observeItem, synchronizeLabels } from "./repository-sync.js";
16
+ import { latestPollAt, PollCycle, RepositoryPoll, RepositoryPollFailure, repositoryFailureLogFields, } from "./cycle.js";
17
+ import { changedItem, FailingItem, failingItem, failingItemPollFailures, logItemEvaluation, } from "./evaluation-failures.js";
18
+ import { evaluateItem, revokeMissingItem } from "./loop-evaluation.js";
19
+ import { markItemGone, observeItem, synchronizeLabels } from "./repository-sync.js";
18
20
  import { ItemHints } from "./hints.js";
19
- /** GitHub tolerates a handful of parallel REST and GraphQL calls per token. */
21
+ import { checkOpenIssues, NO_OPEN_ISSUE_CHECK, OPEN_ISSUE_CHECK_INTERVAL } from "./open-issues.js";
22
+ /** The number of repositories polled in parallel, kept low for GitHub's per-token limits. */
20
23
  const REPOSITORY_CONCURRENCY = 4;
21
24
  const ITEM_CONCURRENCY = 4;
22
25
  const WatchKey = Schema.NonEmptyString.pipe(Schema.brand("GitHubPollWatchKey"));
23
26
  class StoredPollCursor extends Schema.Class("@usine/orchestrator/StoredPollCursor")({
24
- boardVersion: Schema.Literal(4),
27
+ boardVersion: Schema.Literal(5),
28
+ openPullRequests: Schema.Array(Schema.Struct({
29
+ number: ChangedPullRequest.fields.number,
30
+ updatedAt: Schema.DateTimeUtcFromString,
31
+ })),
25
32
  cursor: PollCursor,
26
33
  labelEntityTag: Schema.OptionFromNullOr(EntityTag),
27
34
  watches: Schema.Array(WatchKey).check(Schema.isUnique()),
35
+ failingItems: Schema.Array(FailingItem).pipe(Schema.withDecodingDefaultKey(Effect.succeed([]))),
28
36
  }) {
29
37
  }
30
38
  const cursorKey = (repository) => CursorKey.make(`github-poll:${canonicalRepositoryName(repository.name)}`);
@@ -47,13 +55,25 @@ export class PollingTriggers extends Context.Service()("@usine/orchestrator/Poll
47
55
  const github = yield* GitHubPolling;
48
56
  const loops = yield* LoopControl;
49
57
  const latest = yield* Ref.make(Option.none());
58
+ // Kept across cycles, so a repository whose poll fails keeps its last completion time.
59
+ const completedPolls = yield* Ref.make(new Map());
50
60
  const hints = yield* ItemHints;
51
61
  const ownership = yield* Semaphore.make(1);
62
+ // A failing Item is fetched again only on its repository's first completed cycle in a process
63
+ // or after a reload.
64
+ const retriedFailingItems = yield* Ref.make({
65
+ instance: Option.none(),
66
+ repositories: new Set(),
67
+ });
68
+ // When each repository's open issues were last checked against GitHub.
69
+ const openIssueChecks = yield* Ref.make(new Map());
52
70
  const emptyCursor = (watches) => new StoredPollCursor({
53
- boardVersion: 4,
71
+ boardVersion: 5,
72
+ openPullRequests: [],
54
73
  cursor: PollCursor.empty,
55
74
  labelEntityTag: Option.none(),
56
75
  watches,
76
+ failingItems: [],
57
77
  });
58
78
  const readCursor = Effect.fn("PollingTriggers.readCursor")(function* (watched) {
59
79
  yield* Effect.annotateCurrentSpan({ repository: watched.repository.name });
@@ -74,6 +94,23 @@ export class PollingTriggers extends Context.Service()("@usine/orchestrator/Poll
74
94
  yield* Effect.annotateCurrentSpan({ repository: watched.repository.name });
75
95
  yield* cursors.write(cursorKey(watched.repository), StoredPollCursor, cursor);
76
96
  });
97
+ /** Checks the repository's open issues unless the last check started less than 10 minutes ago. */
98
+ const checkOpenIssuesWhenDue = Effect.fn("PollingTriggers.checkOpenIssuesWhenDue")(function* (watched) {
99
+ yield* Effect.annotateCurrentSpan({ repository: watched.repository.name });
100
+ const key = cursorKey(watched.repository);
101
+ const now = yield* Clock.currentTimeMillis;
102
+ const lastCheck = (yield* Ref.get(openIssueChecks)).get(key);
103
+ if (lastCheck !== undefined &&
104
+ now - lastCheck < Duration.toMillis(OPEN_ISSUE_CHECK_INTERVAL)) {
105
+ yield* Effect.logDebug("Open issues were checked less than 10 minutes ago; skipped", {
106
+ repository: watched.repository.name,
107
+ lastCheckedAt: DateTime.formatIso(DateTime.makeUnsafe(lastCheck)),
108
+ });
109
+ return NO_OPEN_ISSUE_CHECK;
110
+ }
111
+ yield* Ref.update(openIssueChecks, (checks) => new Map(checks).set(key, now));
112
+ return yield* checkOpenIssues(watched.repository, watched.loops);
113
+ });
77
114
  const pollRepository = Effect.fn("PollingTriggers.pollRepository")(function* (watched) {
78
115
  yield* Effect.annotateCurrentSpan({ repository: watched.repository.name });
79
116
  const resets = (yield* budgets.pendingResets()).filter(({ repository }) => canonicalRepositoryName(repository) ===
@@ -91,61 +128,137 @@ export class PollingTriggers extends Context.Service()("@usine/orchestrator/Poll
91
128
  // begin, including on the first cycle after `usine up`.
92
129
  const detected = yield* github.changes(watched.repository.name, stored.cursor);
93
130
  yield* hints.defer(detected.backoffUntil);
131
+ const retrying = (yield* Ref.get(retriedFailingItems)).repositories.has(cursorKey(watched.repository))
132
+ ? []
133
+ : stored.failingItems;
134
+ // Mergeability can change without an updated_at or ETag change, so open PRs stay in the
135
+ // cursor and are refreshed on every poll, even on 304. Cursor version 5 rebuilds this set
136
+ // on upgrade.
137
+ const items = new Map([
138
+ ...retrying.map((failing) => [failing.number, changedItem(failing)]),
139
+ ...stored.openPullRequests.map((item) => [item.number, new ChangedPullRequest(item)]),
140
+ ]);
141
+ if (detected._tag === "RepositoryChanges") {
142
+ for (const item of detected.items)
143
+ items.set(item.number, item);
144
+ yield* Effect.logInfo("Repository changed", {
145
+ repository: watched.repository.name,
146
+ changedItems: detected.items.length,
147
+ backlog: detected.backlog,
148
+ });
149
+ }
150
+ const detectedNumbers = new Set((detected._tag === "RepositoryChanges" ? detected.items : []).map(({ number }) => number));
151
+ // Items fetched only because the cursor kept them: refreshed open pull requests and Items
152
+ // whose Loops failed before this process or instance.
153
+ const cursorOnly = new Set([...stored.openPullRequests, ...retrying]
154
+ .map(({ number }) => number)
155
+ .filter((number) => !detectedNumbers.has(number)));
156
+ if (retrying.length > 0) {
157
+ yield* Effect.logInfo("Evaluating Items whose Loops failed before this process started or the instance was reloaded", {
158
+ repository: watched.repository.name,
159
+ items: retrying.map(({ number }) => number).join(", "),
160
+ });
161
+ }
162
+ const nextPollAt = latestPollAt([detected.nextPollAt, preflight.nextPollAt]);
163
+ yield* Effect.logDebug("Refreshing detected Items and open pull requests", {
164
+ repository: watched.repository.name,
165
+ detection: detected._tag,
166
+ openPullRequests: stored.openPullRequests.length,
167
+ items: items.size,
168
+ });
169
+ const recorded = new Map(stored.failingItems.map((failing) => [failing.number, failing]));
170
+ const evaluations = yield* Effect.forEach(items.values(), (item) => Effect.gen(function* () {
171
+ const observation = yield* observeItem(watched.repository.name, item);
172
+ const cycle = yield* evaluateItem(watched.repository, watched.loops, observation);
173
+ const failing = failingItem(item, observation.projection.contentHash, cycle.failures);
174
+ yield* logItemEvaluation(watched.repository.name, item.number, Option.fromNullishOr(recorded.get(item.number)), failing);
175
+ return { _tag: "Evaluated", item, observation, cycle, failing };
176
+ }).pipe(
177
+ // An Item kept only by the cursor may have been deleted or transferred, and must
178
+ // not stall the repository. Other failures still interrupt the cycle, which retries
179
+ // next time.
180
+ Effect.catchTag("GitHubItemNotFoundError", (error) => Effect.gen(function* () {
181
+ if (!cursorOnly.has(item.number))
182
+ return yield* error;
183
+ const revokedRuns = yield* revokeMissingItem(watched.repository, watched.loops, item._tag === "ChangedIssue" ? "issue" : "pr", item.number);
184
+ const projectionMarkedGone = yield* markItemGone(watched.repository.name, item.number);
185
+ yield* Effect.logWarning("GitHub no longer has an Item the poll cursor kept; it is dropped from the cursor", {
186
+ repository: watched.repository.name,
187
+ item: item.number,
188
+ openPullRequest: stored.openPullRequests.some(({ number }) => number === item.number),
189
+ revokedRuns,
190
+ projectionMarkedGone,
191
+ errorTag: error._tag,
192
+ message: error.message,
193
+ });
194
+ return { _tag: "Missing", revokedRuns };
195
+ }))), { concurrency: ITEM_CONCURRENCY });
196
+ const observed = evaluations.flatMap((evaluation) => evaluation._tag === "Evaluated" ? [evaluation] : []);
197
+ const missingRevokedRuns = evaluations.reduce((sum, evaluation) => sum + (evaluation._tag === "Missing" ? evaluation.revokedRuns : 0), 0);
198
+ const itemCycles = observed.map(({ cycle }) => cycle);
199
+ const openIssueCheck = yield* checkOpenIssuesWhenDue(watched);
200
+ yield* hints.defer(openIssueCheck.nextPollAt);
201
+ // An Item the cycle did not fetch keeps its recorded failures.
202
+ const failingItems = [
203
+ ...stored.failingItems.filter(({ number }) => !items.has(number)),
204
+ ...observed.flatMap(({ failing }) => Option.toArray(failing)),
205
+ ].sort((left, right) => left.number - right.number);
94
206
  const nextCursor = new StoredPollCursor({
95
- boardVersion: 4,
207
+ boardVersion: 5,
96
208
  cursor: detected.cursor,
97
209
  labelEntityTag: preflight.labelEntityTag,
98
210
  watches: watched.watches,
211
+ openPullRequests: observed.flatMap(({ item, observation }) => item._tag === "ChangedPullRequest" && observation.projection.payload.state === "OPEN"
212
+ ? [{ number: item.number, updatedAt: item.updatedAt }]
213
+ : []),
214
+ failingItems,
99
215
  });
100
- const nextPollAt = latestPollAt([detected.nextPollAt, preflight.nextPollAt]);
101
- if (detected._tag === "RepositoryNotModified") {
102
- if (preflight.entityTagChanged) {
103
- yield* writeCursor(watched, nextCursor);
104
- }
105
- yield* Effect.logDebug("Repository unchanged (304)", {
106
- repository: watched.repository.name,
107
- });
108
- return {
109
- changedItems: 0,
110
- submissions: [],
111
- revokedRuns: 0,
112
- failures: preflight.failures,
113
- preflightFindings: preflight.preflightFindings,
114
- nextPollAt,
115
- };
216
+ // Advancing the cursor is the commit point: every changed Item was fetched, evaluated,
217
+ // and submitted or revoked. After a failure, the old cursor stays so the next cycle polls
218
+ // again.
219
+ if (detected._tag === "RepositoryChanges" ||
220
+ items.size > 0 ||
221
+ preflight.entityTagChanged) {
222
+ yield* writeCursor(watched, nextCursor);
116
223
  }
117
- yield* Effect.logInfo("Repository changed", {
118
- repository: watched.repository.name,
119
- changedItems: detected.items.length,
120
- backlog: detected.backlog,
121
- });
122
- const itemCycles = yield* Effect.forEach(detected.items, (item) => observeItem(watched.repository.name, item).pipe(Effect.flatMap((projection) => evaluateItem(watched.repository, watched.loops, projection))), { concurrency: ITEM_CONCURRENCY });
123
- // Advancing the cursor is the commit point: every changed item was
124
- // fetched, evaluated, and submitted or revoked. After a failure the
125
- // old cursor stays so the next cycle re-polls.
126
- yield* writeCursor(watched, nextCursor);
224
+ yield* Ref.update(retriedFailingItems, (retried) => ({
225
+ ...retried,
226
+ repositories: new Set([...retried.repositories, cursorKey(watched.repository)]),
227
+ }));
127
228
  yield* Effect.forEach(resets, budgets.acknowledgeReset, { discard: true });
128
229
  return {
129
- changedItems: detected.items.length,
230
+ // Refreshed open PRs are observed, not reported as changed by
231
+ // GitHub; counting them would make every idle poll look busy.
232
+ changedItems: detected._tag === "RepositoryChanges" ? detected.items.length : 0,
130
233
  submissions: itemCycles.flatMap(({ submissions }) => submissions),
131
- revokedRuns: itemCycles.reduce((sum, cycle) => sum + cycle.revokedRuns, 0),
132
- failures: [...preflight.failures, ...itemCycles.flatMap(({ failures }) => failures)],
234
+ revokedRuns: itemCycles.reduce((sum, cycle) => sum + cycle.revokedRuns, missingRevokedRuns + openIssueCheck.revokedRuns),
235
+ failures: [
236
+ ...preflight.failures,
237
+ ...openIssueCheck.failures,
238
+ ...failingItems.flatMap((failing) => failingItemPollFailures(watched.repository.name, failing)),
239
+ ],
133
240
  preflightFindings: preflight.preflightFindings,
134
- nextPollAt,
241
+ nextPollAt: latestPollAt([nextPollAt, openIssueCheck.nextPollAt]),
135
242
  };
136
243
  }).pipe(Effect.mapError((error) => ({
137
244
  _tag: "InterruptedRepositoryCycle",
138
245
  error,
139
- failures: preflight.failures,
246
+ failures: [
247
+ ...preflight.failures,
248
+ ...stored.failingItems.flatMap((failing) => failingItemPollFailures(watched.repository.name, failing)),
249
+ ],
140
250
  preflightFindings: preflight.preflightFindings,
141
251
  nextPollAt: preflight.nextPollAt,
142
252
  })));
143
253
  });
144
254
  // Bind only dependencies, preserving the caller's clock, logging and
145
255
  // tracing context on each cycle instead of capturing them at layer build.
146
- const repositoryServices = (yield* Effect.context()).pipe(Context.pick(ConfigParser, CycleBudgets, ExpressionEngine, GitHubPolling, ItemProjectionWriter, LabelReconciler, RepositoryLabelProjectionReader, RepositoryLabelProjectionWriter, RunEngine));
256
+ const repositoryServices = (yield* Effect.context()).pipe(Context.pick(ConfigParser, CycleBudgets, ExpressionEngine, GitHubPolling, ItemProjectionReader, ItemProjectionWriter, LabelReconciler, RepositoryLabelProjectionReader, RepositoryLabelProjectionWriter, RunEngine));
147
257
  const poll = Effect.fn("PollingTriggers.poll")(function* (instance) {
148
258
  yield* hints.awaitBackoff;
259
+ yield* Ref.update(retriedFailingItems, (retried) => Option.contains(retried.instance, instance)
260
+ ? retried
261
+ : { instance: Option.some(instance), repositories: new Set() });
149
262
  const paused = new Set((yield* loops.states).filter((state) => state.paused).map((state) => state.loop));
150
263
  for (const loop of instance.loops) {
151
264
  if (loop.trigger.on !== "schedule" && paused.has(loop.name)) {
@@ -161,10 +274,12 @@ export class PollingTriggers extends Context.Service()("@usine/orchestrator/Poll
161
274
  const failures = [];
162
275
  const backoffs = [];
163
276
  const preflightFindings = [];
277
+ const completedAt = yield* DateTime.now;
164
278
  for (const { repository, result } of settled) {
165
279
  if (Result.isSuccess(result)) {
166
280
  cycles.push(result.success);
167
281
  preflightFindings.push(...result.success.preflightFindings);
282
+ yield* Ref.update(completedPolls, (current) => new Map(current).set(canonicalRepositoryName(repository.repository.name), new RepositoryPoll({ repository: repository.repository.name, completedAt })));
168
283
  continue;
169
284
  }
170
285
  const interrupted = result.failure._tag === "InterruptedRepositoryCycle";
@@ -196,7 +311,9 @@ export class PollingTriggers extends Context.Service()("@usine/orchestrator/Poll
196
311
  message: error.message,
197
312
  }));
198
313
  }
314
+ const polls = yield* Ref.get(completedPolls);
199
315
  const cycle = new PollCycle({
316
+ repositoryPolls: watched.flatMap(({ repository }) => Option.toArray(Option.fromNullishOr(polls.get(canonicalRepositoryName(repository.name))))),
200
317
  repositories: watched.length,
201
318
  changedItems: cycles.reduce((sum, cycle) => sum + cycle.changedItems, 0),
202
319
  submissions: cycles.flatMap(({ submissions }) => submissions),
@@ -228,6 +345,18 @@ export class PollingTriggers extends Context.Service()("@usine/orchestrator/Poll
228
345
  // advance a REST cursor or replace the latest complete cycle's findings.
229
346
  const observed = yield* observeItem(watched.repository.name, hint.item);
230
347
  const result = yield* evaluateItem(watched.repository, watched.loops, observed);
348
+ // The self-write changed the Item, so the next poll fetches it again
349
+ // and records these failures for Needs you.
350
+ for (const failure of result.failures) {
351
+ yield* Effect.logWarning("Self-write Hint could not evaluate a Loop on the Item", {
352
+ repository: hint.repository,
353
+ item: hint.item.number,
354
+ loop: failure.loop,
355
+ stage: failure.stage,
356
+ errorTag: failure.errorTag,
357
+ message: failure.message,
358
+ });
359
+ }
231
360
  yield* Effect.logInfo("Self-write Hint refreshed the Item", {
232
361
  repository: hint.repository,
233
362
  item: hint.item.number,
@@ -244,20 +373,41 @@ export class PollingTriggers extends Context.Service()("@usine/orchestrator/Poll
244
373
  ...repositoryFailureLogFields(error),
245
374
  });
246
375
  })), ownership.withPermits(1)));
247
- const waitForNextPoll = (instance, target) => Effect.gen(function* () {
376
+ // An accepted reload ends the wait for `intervalAt`, never the wait for
377
+ // `requestedAt`, the time GitHub asked for.
378
+ const waitForNextPoll = (instances, polled, intervalAt, requestedAt) => Effect.gen(function* () {
379
+ let target = Math.max(intervalAt, requestedAt);
380
+ let seen = polled;
248
381
  while (true) {
249
382
  const remaining = target - (yield* Clock.currentTimeMillis);
250
383
  if (remaining <= 0)
251
384
  return;
252
- const hint = yield* Effect.raceFirst(hints.take.pipe(Effect.map(Option.some)), Effect.sleep(Duration.millis(remaining)).pipe(Effect.as(Option.none())));
253
- if (Option.isNone(hint))
385
+ const wake = yield* Effect.raceAllFirst([
386
+ Effect.sleep(Duration.millis(remaining)).pipe(Effect.map(() => ({ _tag: "Due" }))),
387
+ hints.take.pipe(Effect.map((hint) => ({ _tag: "Hint", hint }))),
388
+ reloadedFrom(instances, seen).pipe(Effect.map((instance) => ({ _tag: "Reloaded", instance }))),
389
+ ]);
390
+ if (wake._tag === "Due")
254
391
  return;
255
- yield* refreshHint(instance, hint.value);
392
+ if (wake._tag === "Hint") {
393
+ yield* refreshHint(yield* instances.get, wake.hint);
394
+ continue;
395
+ }
396
+ seen = wake.instance;
397
+ target = requestedAt;
398
+ const sleepMs = requestedAt - (yield* Clock.currentTimeMillis);
399
+ if (sleepMs > 0) {
400
+ yield* Effect.logInfo("Instance reloaded; the next poll waits for the time GitHub asked for", { sleepMs });
401
+ }
402
+ else {
403
+ yield* Effect.logInfo("Instance reloaded; polling now instead of after poll_interval");
404
+ }
256
405
  }
257
406
  });
258
407
  // `run` never returns, so wrapping it in Effect.fn would open a span that
259
408
  // never closes; `poll` opens the span for each cycle.
260
- const run = (instance) => Effect.gen(function* () {
409
+ const run = (instances) => Effect.gen(function* () {
410
+ const instance = yield* instances.get;
261
411
  const startedAt = yield* Clock.currentTimeMillis;
262
412
  const result = yield* Effect.result(poll(instance));
263
413
  if (Result.isFailure(result)) {
@@ -273,12 +423,12 @@ export class PollingTriggers extends Context.Service()("@usine/orchestrator/Poll
273
423
  }
274
424
  const cycle = result.success;
275
425
  const intervalAt = startedAt + instance.config.settings.pollInterval * 1_000;
276
- const target = Option.match(cycle.nextPollAt, {
277
- onNone: () => intervalAt,
278
- onSome: (value) => Math.max(intervalAt, DateTime.toEpochMillis(value)),
426
+ const requestedAt = Option.match(cycle.nextPollAt, {
427
+ onNone: () => 0,
428
+ onSome: DateTime.toEpochMillis,
279
429
  });
280
430
  const now = yield* Clock.currentTimeMillis;
281
- const sleepMs = Math.max(0, target - now);
431
+ const sleepMs = Math.max(0, Math.max(intervalAt, requestedAt) - now);
282
432
  yield* Effect.logInfo("Poll cycle complete", {
283
433
  repositories: cycle.repositories,
284
434
  changedItems: cycle.changedItems,
@@ -288,7 +438,7 @@ export class PollingTriggers extends Context.Service()("@usine/orchestrator/Poll
288
438
  preflightFindings: cycle.preflightFindings.length,
289
439
  sleepMs,
290
440
  });
291
- yield* waitForNextPoll(instance, target);
441
+ yield* waitForNextPoll(instances, instance, intervalAt, requestedAt);
292
442
  }).pipe(Effect.forever);
293
443
  return { latest: Ref.get(latest), poll, run, hint: hints.offer };
294
444
  })).pipe(Layer.provide(ItemHints.layer));