| 48 | } |
| 49 | |
| 50 | export class RuntimeEvolveWorker implements DurableMemoryWorkerLike { |
| 51 | readonly #store: RuntimeStateStore; |
| 52 | readonly #logger: RuntimeEvolveWorkerOptions["logger"]; |
| 53 | readonly #executeClaimedJob: (record: PostRunJobRecord) => Promise<void>; |
| 54 | readonly #claimedBy: string; |
| 55 | readonly #leaseSeconds: number; |
| 56 | readonly #pollIntervalMs: number; |
| 57 | readonly #maxConcurrency: number; |
| 58 | readonly #maxAttempts: number; |
| 59 | readonly #retryDelayMs: number; |
| 60 | #stopped = false; |
| 61 | #task: Promise<void> | null = null; |
| 62 | #wakeResolver: (() => void) | null = null; |
| 63 | |
| 64 | constructor(options: RuntimeEvolveWorkerOptions) { |
| 65 | this.#store = options.store; |
| 66 | this.#logger = options.logger; |
| 67 | this.#claimedBy = options.claimedBy ?? DEFAULT_CLAIMED_BY; |
| 68 | this.#executeClaimedJob = |
| 69 | options.executeClaimedJob ?? |
| 70 | ((record) => |
| 71 | processEvolveJob({ |
| 72 | store: this.#store, |
| 73 | record, |
| 74 | memoryService: options.memoryService, |
| 75 | })); |
| 76 | this.#leaseSeconds = options.leaseSeconds ?? DEFAULT_LEASE_SECONDS; |
| 77 | this.#pollIntervalMs = options.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS; |
| 78 | this.#maxConcurrency = options.maxConcurrency ?? workerMaxConcurrency(); |
| 79 | this.#maxAttempts = Math.max(1, options.maxAttempts ?? DEFAULT_MAX_ATTEMPTS); |
| 80 | this.#retryDelayMs = Math.max(0, options.retryDelayMs ?? DEFAULT_RETRY_DELAY_MS); |
| 81 | } |
| 82 | |
| 83 | async start(): Promise<void> { |
| 84 | if (this.#task) { |
| 85 | return; |
| 86 | } |
| 87 | this.#stopped = false; |
| 88 | this.#task = this.#runLoop(); |
| 89 | } |
| 90 | |
| 91 | wake(): void { |
| 92 | const resolve = this.#wakeResolver; |
| 93 | this.#wakeResolver = null; |
| 94 | resolve?.(); |
| 95 | } |
| 96 | |
| 97 | async close(): Promise<void> { |
| 98 | this.#stopped = true; |
| 99 | this.wake(); |
| 100 | const task = this.#task; |
| 101 | this.#task = null; |
| 102 | await task; |
| 103 | } |
| 104 | |
| 105 | async processAvailableJobsOnce(): Promise<number> { |
| 106 | const recovered = this.#recoverExpiredClaims(); |
| 107 | const claimed = this.#store.claimPostRunJobs({ |
nothing calls this directly
no outgoing calls
no test coverage detected