@webpieces/cloudtasks-client 0.3.278 → 0.3.280

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webpieces/cloudtasks-client",
3
- "version": "0.3.278",
3
+ "version": "0.3.280",
4
4
  "description": "Cloud Tasks enqueue client generated from a shared @PubSub API contract (twin of http-client)",
5
5
  "type": "commonjs",
6
6
  "main": "./src/index.js",
@@ -23,9 +23,9 @@
23
23
  "access": "public"
24
24
  },
25
25
  "dependencies": {
26
- "@webpieces/core-context": "0.3.278",
27
- "@webpieces/core-util": "0.3.278",
28
- "@webpieces/gcp-identity": "0.3.278",
26
+ "@webpieces/core-context": "0.3.280",
27
+ "@webpieces/core-util": "0.3.280",
28
+ "@webpieces/gcp-identity": "0.3.280",
29
29
  "@google-cloud/tasks": "5.5.2",
30
30
  "inversify": "7.10.4",
31
31
  "reflect-metadata": "0.2.2"
@@ -101,7 +101,7 @@ let CloudTaskScheduler = class CloudTaskScheduler {
101
101
  };
102
102
  exports.CloudTaskScheduler = CloudTaskScheduler;
103
103
  exports.CloudTaskScheduler = CloudTaskScheduler = tslib_1.__decorate([
104
- (0, core_context_1.provideSingleton)(),
104
+ (0, core_context_1.provideFrameworkSingleton)(),
105
105
  (0, inversify_1.injectable)(),
106
106
  tslib_1.__param(0, (0, inversify_1.inject)(TaskTypes_1.TaskInvoker)),
107
107
  tslib_1.__metadata("design:paramtypes", [TaskTypes_1.TaskInvoker])
@@ -1 +1 @@
1
- {"version":3,"file":"CloudTaskScheduler.js","sourceRoot":"","sources":["../../../../../packages/cloud/cloudtasks-client/src/CloudTaskScheduler.ts"],"names":[],"mappings":";;;;AAAA,yCAA+C;AAC/C,0DAA2D;AAC3D,0DAAyD;AACzD,oDAAkD;AAClD,2CAAsE;AACtE,uDAAwF;AAExF,MAAM,GAAG,GAAG,sBAAU,CAAC,SAAS,CAAC,oBAAoB,CAAC,CAAC;AAEvD;;;;;GAKG;AACH,MAAa,eAAe;IACxB,qFAAqF;IACrF,SAAS,CAAU;IACnB,6CAA6C;IAC7C,kBAAkB,CAAU;IAE5B,YAAY,SAAkB,EAAE,kBAA2B;QACvD,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;QAC3B,IAAI,CAAC,kBAAkB,GAAG,kBAAkB,CAAC;IACjD,CAAC;CACJ;AAVD,0CAUC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAGI,IAAM,kBAAkB,GAAxB,MAAM,kBAAkB;IAEe;IAD1C,YAC0C,OAAoB;QAApB,YAAO,GAAP,OAAO,CAAa;IAC3D,CAAC;IAEJ,2EAA2E;IAC3E,KAAK,CAAC,UAAU,CAAC,QAA6B,EAAE,IAAsB;QAClE,OAAO,IAAI,CAAC,YAAY,CACpB,IAAI,wBAAY,CAAC,SAAS,EAAE,IAAI,EAAE,kBAAkB,EAAE,IAAI,EAAE,SAAS,CAAC,EACtE,QAAQ,CACX,CAAC;IACN,CAAC;IAED,wFAAwF;IACxF,KAAK,CAAC,QAAQ,CACV,QAA6B,EAC7B,cAAsB,EACtB,IAAsB;QAEtB,OAAO,IAAI,CAAC,YAAY,CACpB,IAAI,wBAAY,CAAC,cAAc,EAAE,IAAI,EAAE,kBAAkB,EAAE,IAAI,EAAE,SAAS,CAAC,EAC3E,QAAQ,CACX,CAAC;IACN,CAAC;IAED,0CAA0C;IAC1C,KAAK,CAAC,SAAS,CAAC,GAAiB;QAC7B,MAAM,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IACnC,CAAC;IAEO,KAAK,CAAC,YAAY,CACtB,IAAkB,EAClB,QAA6B;QAE7B,IAAI,CAAC,6BAAc,CAAC,QAAQ,EAAE,EAAE,CAAC;YAC7B,MAAM,IAAI,KAAK,CACX,+EAA+E,CAClF,CAAC;QACN,CAAC;QACD,MAAM,KAAK,GAAG,IAAI,+BAAa,CAAC,IAAI,CAAC,CAAC;QACtC,IAAA,kCAAgB,EAAC,KAAK,CAAC,CAAC;QACxB,mIAAmI;QACnI,IAAI,CAAC;YACD,MAAM,QAAQ,EAAE,CAAC;QACrB,CAAC;gBAAS,CAAC;YACP,IAAA,oCAAkB,GAAE,CAAC;QACzB,CAAC;QACD,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;YAChB,MAAM,IAAI,KAAK,CACX,4EAA4E;gBAC5E,oCAAoC,CACvC,CAAC;QACN,CAAC;QACD,GAAG,CAAC,KAAK,CAAC,kBAAkB,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;QACnD,OAAO,KAAK,CAAC,MAAM,CAAC;IACxB,CAAC;CACJ,CAAA;AAxDY,gDAAkB;6BAAlB,kBAAkB;IAF9B,IAAA,+BAAgB,GAAE;IAClB,IAAA,sBAAU,GAAE;IAGJ,mBAAA,IAAA,kBAAM,EAAC,uBAAW,CAAC,CAAA;6CAA2B,uBAAW;GAFrD,kBAAkB,CAwD9B","sourcesContent":["import { inject, injectable } from 'inversify';\nimport { provideSingleton } from '@webpieces/core-context';\nimport { RequestContext } from '@webpieces/core-context';\nimport { LogManager } from '@webpieces/core-util';\nimport { TaskInvoker, JobReference, ScheduleInfo } from './TaskTypes';\nimport { ScheduleFrame, setScheduleFrame, clearScheduleFrame } from './ScheduleContext';\n\nconst log = LogManager.getLogger('CloudTaskScheduler');\n\n/**\n * Options for a scheduled task. These are QUEUE/TRANSPORT knobs (dedup, deadline)\n * that belong on the enqueue CALL, never on the shared API method — the controller\n * implementing that method has no use for them. See CloudTaskScheduler's class doc\n * for the full rationale.\n */\nexport class ScheduleOptions {\n /** Deterministic Cloud Task name → idempotent dedup (duplicate = ALREADY_EXISTS). */\n dedupName?: string;\n /** Per-task dispatch deadline in seconds. */\n taskTimeoutSeconds?: number;\n\n constructor(dedupName?: string, taskTimeoutSeconds?: number) {\n this.dedupName = dedupName;\n this.taskTimeoutSeconds = taskTimeoutSeconds;\n }\n}\n\n/**\n * Schedules Cloud Tasks. You wrap an enqueue-client call in a lambda so the shared\n * contract's method signature stays `foo(req)` on both client and controller; the\n * scheduling options ride out-of-band in the schedule frame:\n *\n * await scheduler.addToQueue(() => taskClient.sendEmail(req), { dedupName: id });\n * await scheduler.schedule(() => taskClient.sendEmail(req), runAtEpochMs);\n *\n * Must be called inside an active RequestContext (a server request scope).\n *\n * WHY scheduling options are here and NOT parameters on the API method\n * ------------------------------------------------------------------------\n * The enqueue client and the controller implement the SAME abstract API method\n * (`sendEmail(req): Promise<void>`). Scheduling options — `dedupName`, \"run in the\n * future\", `taskTimeoutSeconds` — are QUEUE/TRANSPORT concerns, not part of the\n * business contract, so they must not appear on the method signature:\n *\n * - They are meaningless on the SERVER side. The controller's `sendEmail` just does\n * the work (send the email). It has no use for `dedupName` (a Cloud Tasks resource\n * name), a future run-time (Cloud Tasks already delivered it), or a dispatch\n * deadline. Putting them on the method would force the controller to accept and\n * ignore transport metadata it can't act on.\n * - They vary per CALL SITE, not per method. The same `sendEmail` might be enqueued\n * plain in one place, deduped in another, and scheduled for later in a third. That\n * is a property of THIS enqueue, not of the API — so it belongs on the enqueue\n * call (the scheduler), exactly like Cloud Tasks itself separates the task's\n * schedule/dedup/deadline from the HTTP body it delivers.\n * - Symmetry with RPC: an http-client RPC call is `foo(req)` with no transport knobs\n * in the contract; the async (queue) client keeps that same clean contract and\n * moves the queue knobs to the scheduler wrapper.\n *\n * So the rule is: the API method is `method(req)` on BOTH sides forever; anything\n * queue-shaped (dedup, delay, timeout, cancel) lives on CloudTaskScheduler /\n * ScheduleOptions here, never on the API.\n */\n@provideSingleton()\n@injectable()\nexport class CloudTaskScheduler {\n constructor(\n @inject(TaskInvoker) private readonly invoker: TaskInvoker,\n ) {}\n\n /** Enqueue a task to run as soon as possible. Returns its JobReference. */\n async addToQueue(runnable: () => Promise<void>, opts?: ScheduleOptions): Promise<JobReference> {\n return this.runWithFrame(\n new ScheduleInfo(undefined, opts?.taskTimeoutSeconds, opts?.dedupName),\n runnable,\n );\n }\n\n /** Enqueue a task to run at an absolute epoch-millis time. Returns its JobReference. */\n async schedule(\n runnable: () => Promise<void>,\n epochMsToRunAt: number,\n opts?: ScheduleOptions,\n ): Promise<JobReference> {\n return this.runWithFrame(\n new ScheduleInfo(epochMsToRunAt, opts?.taskTimeoutSeconds, opts?.dedupName),\n runnable,\n );\n }\n\n /** Cancel a previously scheduled task. */\n async cancelJob(ref: JobReference): Promise<void> {\n await this.invoker.delete(ref);\n }\n\n private async runWithFrame(\n info: ScheduleInfo,\n runnable: () => Promise<void>,\n ): Promise<JobReference> {\n if (!RequestContext.isActive()) {\n throw new Error(\n 'CloudTaskScheduler must run inside a RequestContext (a server request scope).',\n );\n }\n const frame = new ScheduleFrame(info);\n setScheduleFrame(frame);\n // eslint-disable-next-line @webpieces/no-unmanaged-exceptions -- always clear the frame; the runnable's error propagates unchanged\n try {\n await runnable();\n } finally {\n clearScheduleFrame();\n }\n if (!frame.jobRef) {\n throw new Error(\n 'CloudTaskScheduler runnable did not enqueue a task — the lambda must call ' +\n 'a task-client method exactly once.',\n );\n }\n log.debug(`scheduled task ${frame.jobRef.taskId}`);\n return frame.jobRef;\n }\n}\n"]}
1
+ {"version":3,"file":"CloudTaskScheduler.js","sourceRoot":"","sources":["../../../../../packages/cloud/cloudtasks-client/src/CloudTaskScheduler.ts"],"names":[],"mappings":";;;;AAAA,yCAA+C;AAC/C,0DAAoE;AACpE,0DAAyD;AACzD,oDAAkD;AAClD,2CAAsE;AACtE,uDAAwF;AAExF,MAAM,GAAG,GAAG,sBAAU,CAAC,SAAS,CAAC,oBAAoB,CAAC,CAAC;AAEvD;;;;;GAKG;AACH,MAAa,eAAe;IACxB,qFAAqF;IACrF,SAAS,CAAU;IACnB,6CAA6C;IAC7C,kBAAkB,CAAU;IAE5B,YAAY,SAAkB,EAAE,kBAA2B;QACvD,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;QAC3B,IAAI,CAAC,kBAAkB,GAAG,kBAAkB,CAAC;IACjD,CAAC;CACJ;AAVD,0CAUC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAGI,IAAM,kBAAkB,GAAxB,MAAM,kBAAkB;IAEe;IAD1C,YAC0C,OAAoB;QAApB,YAAO,GAAP,OAAO,CAAa;IAC3D,CAAC;IAEJ,2EAA2E;IAC3E,KAAK,CAAC,UAAU,CAAC,QAA6B,EAAE,IAAsB;QAClE,OAAO,IAAI,CAAC,YAAY,CACpB,IAAI,wBAAY,CAAC,SAAS,EAAE,IAAI,EAAE,kBAAkB,EAAE,IAAI,EAAE,SAAS,CAAC,EACtE,QAAQ,CACX,CAAC;IACN,CAAC;IAED,wFAAwF;IACxF,KAAK,CAAC,QAAQ,CACV,QAA6B,EAC7B,cAAsB,EACtB,IAAsB;QAEtB,OAAO,IAAI,CAAC,YAAY,CACpB,IAAI,wBAAY,CAAC,cAAc,EAAE,IAAI,EAAE,kBAAkB,EAAE,IAAI,EAAE,SAAS,CAAC,EAC3E,QAAQ,CACX,CAAC;IACN,CAAC;IAED,0CAA0C;IAC1C,KAAK,CAAC,SAAS,CAAC,GAAiB;QAC7B,MAAM,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IACnC,CAAC;IAEO,KAAK,CAAC,YAAY,CACtB,IAAkB,EAClB,QAA6B;QAE7B,IAAI,CAAC,6BAAc,CAAC,QAAQ,EAAE,EAAE,CAAC;YAC7B,MAAM,IAAI,KAAK,CACX,+EAA+E,CAClF,CAAC;QACN,CAAC;QACD,MAAM,KAAK,GAAG,IAAI,+BAAa,CAAC,IAAI,CAAC,CAAC;QACtC,IAAA,kCAAgB,EAAC,KAAK,CAAC,CAAC;QACxB,mIAAmI;QACnI,IAAI,CAAC;YACD,MAAM,QAAQ,EAAE,CAAC;QACrB,CAAC;gBAAS,CAAC;YACP,IAAA,oCAAkB,GAAE,CAAC;QACzB,CAAC;QACD,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;YAChB,MAAM,IAAI,KAAK,CACX,4EAA4E;gBAC5E,oCAAoC,CACvC,CAAC;QACN,CAAC;QACD,GAAG,CAAC,KAAK,CAAC,kBAAkB,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;QACnD,OAAO,KAAK,CAAC,MAAM,CAAC;IACxB,CAAC;CACJ,CAAA;AAxDY,gDAAkB;6BAAlB,kBAAkB;IAF9B,IAAA,wCAAyB,GAAE;IAC3B,IAAA,sBAAU,GAAE;IAGJ,mBAAA,IAAA,kBAAM,EAAC,uBAAW,CAAC,CAAA;6CAA2B,uBAAW;GAFrD,kBAAkB,CAwD9B","sourcesContent":["import { inject, injectable } from 'inversify';\nimport { provideFrameworkSingleton } from '@webpieces/core-context';\nimport { RequestContext } from '@webpieces/core-context';\nimport { LogManager } from '@webpieces/core-util';\nimport { TaskInvoker, JobReference, ScheduleInfo } from './TaskTypes';\nimport { ScheduleFrame, setScheduleFrame, clearScheduleFrame } from './ScheduleContext';\n\nconst log = LogManager.getLogger('CloudTaskScheduler');\n\n/**\n * Options for a scheduled task. These are QUEUE/TRANSPORT knobs (dedup, deadline)\n * that belong on the enqueue CALL, never on the shared API method — the controller\n * implementing that method has no use for them. See CloudTaskScheduler's class doc\n * for the full rationale.\n */\nexport class ScheduleOptions {\n /** Deterministic Cloud Task name → idempotent dedup (duplicate = ALREADY_EXISTS). */\n dedupName?: string;\n /** Per-task dispatch deadline in seconds. */\n taskTimeoutSeconds?: number;\n\n constructor(dedupName?: string, taskTimeoutSeconds?: number) {\n this.dedupName = dedupName;\n this.taskTimeoutSeconds = taskTimeoutSeconds;\n }\n}\n\n/**\n * Schedules Cloud Tasks. You wrap an enqueue-client call in a lambda so the shared\n * contract's method signature stays `foo(req)` on both client and controller; the\n * scheduling options ride out-of-band in the schedule frame:\n *\n * await scheduler.addToQueue(() => taskClient.sendEmail(req), { dedupName: id });\n * await scheduler.schedule(() => taskClient.sendEmail(req), runAtEpochMs);\n *\n * Must be called inside an active RequestContext (a server request scope).\n *\n * WHY scheduling options are here and NOT parameters on the API method\n * ------------------------------------------------------------------------\n * The enqueue client and the controller implement the SAME abstract API method\n * (`sendEmail(req): Promise<void>`). Scheduling options — `dedupName`, \"run in the\n * future\", `taskTimeoutSeconds` — are QUEUE/TRANSPORT concerns, not part of the\n * business contract, so they must not appear on the method signature:\n *\n * - They are meaningless on the SERVER side. The controller's `sendEmail` just does\n * the work (send the email). It has no use for `dedupName` (a Cloud Tasks resource\n * name), a future run-time (Cloud Tasks already delivered it), or a dispatch\n * deadline. Putting them on the method would force the controller to accept and\n * ignore transport metadata it can't act on.\n * - They vary per CALL SITE, not per method. The same `sendEmail` might be enqueued\n * plain in one place, deduped in another, and scheduled for later in a third. That\n * is a property of THIS enqueue, not of the API — so it belongs on the enqueue\n * call (the scheduler), exactly like Cloud Tasks itself separates the task's\n * schedule/dedup/deadline from the HTTP body it delivers.\n * - Symmetry with RPC: an http-client RPC call is `foo(req)` with no transport knobs\n * in the contract; the async (queue) client keeps that same clean contract and\n * moves the queue knobs to the scheduler wrapper.\n *\n * So the rule is: the API method is `method(req)` on BOTH sides forever; anything\n * queue-shaped (dedup, delay, timeout, cancel) lives on CloudTaskScheduler /\n * ScheduleOptions here, never on the API.\n */\n@provideFrameworkSingleton()\n@injectable()\nexport class CloudTaskScheduler {\n constructor(\n @inject(TaskInvoker) private readonly invoker: TaskInvoker,\n ) {}\n\n /** Enqueue a task to run as soon as possible. Returns its JobReference. */\n async addToQueue(runnable: () => Promise<void>, opts?: ScheduleOptions): Promise<JobReference> {\n return this.runWithFrame(\n new ScheduleInfo(undefined, opts?.taskTimeoutSeconds, opts?.dedupName),\n runnable,\n );\n }\n\n /** Enqueue a task to run at an absolute epoch-millis time. Returns its JobReference. */\n async schedule(\n runnable: () => Promise<void>,\n epochMsToRunAt: number,\n opts?: ScheduleOptions,\n ): Promise<JobReference> {\n return this.runWithFrame(\n new ScheduleInfo(epochMsToRunAt, opts?.taskTimeoutSeconds, opts?.dedupName),\n runnable,\n );\n }\n\n /** Cancel a previously scheduled task. */\n async cancelJob(ref: JobReference): Promise<void> {\n await this.invoker.delete(ref);\n }\n\n private async runWithFrame(\n info: ScheduleInfo,\n runnable: () => Promise<void>,\n ): Promise<JobReference> {\n if (!RequestContext.isActive()) {\n throw new Error(\n 'CloudTaskScheduler must run inside a RequestContext (a server request scope).',\n );\n }\n const frame = new ScheduleFrame(info);\n setScheduleFrame(frame);\n // eslint-disable-next-line @webpieces/no-unmanaged-exceptions -- always clear the frame; the runnable's error propagates unchanged\n try {\n await runnable();\n } finally {\n clearScheduleFrame();\n }\n if (!frame.jobRef) {\n throw new Error(\n 'CloudTaskScheduler runnable did not enqueue a task — the lambda must call ' +\n 'a task-client method exactly once.',\n );\n }\n log.debug(`scheduled task ${frame.jobRef.taskId}`);\n return frame.jobRef;\n }\n}\n"]}
@@ -74,7 +74,7 @@ let GcpTaskInvoker = class GcpTaskInvoker extends TaskTypes_1.TaskInvoker {
74
74
  };
75
75
  exports.GcpTaskInvoker = GcpTaskInvoker;
76
76
  exports.GcpTaskInvoker = GcpTaskInvoker = tslib_1.__decorate([
77
- (0, core_context_1.provideSingleton)(),
77
+ (0, core_context_1.provideFrameworkSingleton)(),
78
78
  (0, inversify_1.injectable)()
79
79
  ], GcpTaskInvoker);
80
80
  //# sourceMappingURL=GcpTaskInvoker.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"GcpTaskInvoker.js","sourceRoot":"","sources":["../../../../../packages/cloud/cloudtasks-client/src/GcpTaskInvoker.ts"],"names":[],"mappings":"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","sourcesContent":["import { injectable } from 'inversify';\nimport { CloudTasksClient, protos } from '@google-cloud/tasks';\nimport { provideSingleton } from '@webpieces/core-context';\nimport {\n getProjectId,\n getRegion,\n getRuntimeServiceAccountEmail,\n} from '@webpieces/gcp-identity';\nimport { LogManager } from '@webpieces/core-util';\nimport { TaskInvoker, TaskRequest, JobReference } from './TaskTypes';\n\nconst log = LogManager.getLogger('GcpTaskInvoker');\n\ntype ITask = protos.google.cloud.tasks.v2.ITask;\n\n/**\n * TaskInvoker that enqueues to Google Cloud Tasks (`@google-cloud/tasks`). Builds an\n * HTTP-target task delivered as POST to `targetUrl + path`, authenticated per the\n * endpoint's auth mode (OIDC token minted as this service's runtime SA, or a\n * shared-secret header). The task name is derived from the dedup name for idempotency\n * (a duplicate enqueue is rejected ALREADY_EXISTS = idempotent success upstream).\n */\n@provideSingleton()\n@injectable()\nexport class GcpTaskInvoker extends TaskInvoker {\n private readonly client = new CloudTasksClient();\n\n override async enqueue(request: TaskRequest): Promise<JobReference> {\n const projectId = await getProjectId();\n const region = await getRegion();\n const parent = this.client.queuePath(projectId, region, request.queueName);\n\n const task = await this.buildTask(request, parent);\n const result = await this.client.createTask({ parent: parent, task: task });\n const created = result[0];\n const name = created.name ?? request.scheduleInfo.dedupName ?? 'unknown';\n log.info(`enqueued cloud task ${name}`);\n return new JobReference(name);\n }\n\n override async delete(ref: JobReference): Promise<void> {\n await this.client.deleteTask({ name: ref.taskId });\n }\n\n private async buildTask(request: TaskRequest, parent: string): Promise<ITask> {\n const headers = new Map<string, string>(request.contextHeaders);\n headers.set('content-type', 'application/json');\n\n const httpRequest: protos.google.cloud.tasks.v2.IHttpRequest = {\n httpMethod: 'POST',\n url: request.targetUrl + request.path,\n headers: Object.fromEntries(headers),\n body: Buffer.from(JSON.stringify(request.body ?? {}), 'utf8').toString('base64'),\n };\n await this.applyAuth(request, httpRequest, headers);\n\n const task: ITask = { httpRequest: httpRequest };\n if (request.scheduleInfo.dedupName) {\n task.name = `${parent}/tasks/${request.scheduleInfo.dedupName}`;\n }\n if (request.scheduleInfo.epochMsToRunAt) {\n task.scheduleTime = { seconds: Math.floor(request.scheduleInfo.epochMsToRunAt / 1000) };\n }\n if (request.scheduleInfo.taskTimeoutSeconds) {\n task.dispatchDeadline = { seconds: request.scheduleInfo.taskTimeoutSeconds };\n }\n return task;\n }\n\n private async applyAuth(\n request: TaskRequest,\n httpRequest: protos.google.cloud.tasks.v2.IHttpRequest,\n headers: Map<string, string>,\n ): Promise<void> {\n const mode = request.authMode;\n if (mode.kind === 'oidc') {\n httpRequest.oidcToken = {\n serviceAccountEmail: await getRuntimeServiceAccountEmail(),\n audience: request.targetUrl,\n };\n return;\n }\n if (mode.kind === 'shared-secret') {\n const secret = process.env[mode.secretEnv];\n if (secret) {\n headers.set('x-webpieces-shared-secret', secret);\n httpRequest.headers = Object.fromEntries(headers);\n }\n }\n }\n}\n"]}
1
+ {"version":3,"file":"GcpTaskInvoker.js","sourceRoot":"","sources":["../../../../../packages/cloud/cloudtasks-client/src/GcpTaskInvoker.ts"],"names":[],"mappings":"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","sourcesContent":["import { injectable } from 'inversify';\nimport { CloudTasksClient, protos } from '@google-cloud/tasks';\nimport { provideFrameworkSingleton } from '@webpieces/core-context';\nimport {\n getProjectId,\n getRegion,\n getRuntimeServiceAccountEmail,\n} from '@webpieces/gcp-identity';\nimport { LogManager } from '@webpieces/core-util';\nimport { TaskInvoker, TaskRequest, JobReference } from './TaskTypes';\n\nconst log = LogManager.getLogger('GcpTaskInvoker');\n\ntype ITask = protos.google.cloud.tasks.v2.ITask;\n\n/**\n * TaskInvoker that enqueues to Google Cloud Tasks (`@google-cloud/tasks`). Builds an\n * HTTP-target task delivered as POST to `targetUrl + path`, authenticated per the\n * endpoint's auth mode (OIDC token minted as this service's runtime SA, or a\n * shared-secret header). The task name is derived from the dedup name for idempotency\n * (a duplicate enqueue is rejected ALREADY_EXISTS = idempotent success upstream).\n */\n@provideFrameworkSingleton()\n@injectable()\nexport class GcpTaskInvoker extends TaskInvoker {\n private readonly client = new CloudTasksClient();\n\n override async enqueue(request: TaskRequest): Promise<JobReference> {\n const projectId = await getProjectId();\n const region = await getRegion();\n const parent = this.client.queuePath(projectId, region, request.queueName);\n\n const task = await this.buildTask(request, parent);\n const result = await this.client.createTask({ parent: parent, task: task });\n const created = result[0];\n const name = created.name ?? request.scheduleInfo.dedupName ?? 'unknown';\n log.info(`enqueued cloud task ${name}`);\n return new JobReference(name);\n }\n\n override async delete(ref: JobReference): Promise<void> {\n await this.client.deleteTask({ name: ref.taskId });\n }\n\n private async buildTask(request: TaskRequest, parent: string): Promise<ITask> {\n const headers = new Map<string, string>(request.contextHeaders);\n headers.set('content-type', 'application/json');\n\n const httpRequest: protos.google.cloud.tasks.v2.IHttpRequest = {\n httpMethod: 'POST',\n url: request.targetUrl + request.path,\n headers: Object.fromEntries(headers),\n body: Buffer.from(JSON.stringify(request.body ?? {}), 'utf8').toString('base64'),\n };\n await this.applyAuth(request, httpRequest, headers);\n\n const task: ITask = { httpRequest: httpRequest };\n if (request.scheduleInfo.dedupName) {\n task.name = `${parent}/tasks/${request.scheduleInfo.dedupName}`;\n }\n if (request.scheduleInfo.epochMsToRunAt) {\n task.scheduleTime = { seconds: Math.floor(request.scheduleInfo.epochMsToRunAt / 1000) };\n }\n if (request.scheduleInfo.taskTimeoutSeconds) {\n task.dispatchDeadline = { seconds: request.scheduleInfo.taskTimeoutSeconds };\n }\n return task;\n }\n\n private async applyAuth(\n request: TaskRequest,\n httpRequest: protos.google.cloud.tasks.v2.IHttpRequest,\n headers: Map<string, string>,\n ): Promise<void> {\n const mode = request.authMode;\n if (mode.kind === 'oidc') {\n httpRequest.oidcToken = {\n serviceAccountEmail: await getRuntimeServiceAccountEmail(),\n audience: request.targetUrl,\n };\n return;\n }\n if (mode.kind === 'shared-secret') {\n const secret = process.env[mode.secretEnv];\n if (secret) {\n headers.set('x-webpieces-shared-secret', secret);\n httpRequest.headers = Object.fromEntries(headers);\n }\n }\n }\n}\n"]}
@@ -109,7 +109,7 @@ let InMemoryTaskInvoker = class InMemoryTaskInvoker extends TaskTypes_1.TaskInvo
109
109
  };
110
110
  exports.InMemoryTaskInvoker = InMemoryTaskInvoker;
111
111
  exports.InMemoryTaskInvoker = InMemoryTaskInvoker = tslib_1.__decorate([
112
- (0, core_context_1.provideSingleton)(),
112
+ (0, core_context_1.provideFrameworkSingleton)(),
113
113
  (0, inversify_1.injectable)()
114
114
  ], InMemoryTaskInvoker);
115
115
  //# sourceMappingURL=InMemoryTaskInvoker.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"InMemoryTaskInvoker.js","sourceRoot":"","sources":["../../../../../packages/cloud/cloudtasks-client/src/InMemoryTaskInvoker.ts"],"names":[],"mappings":"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","sourcesContent":["import { injectable } from 'inversify';\nimport { provideSingleton } from '@webpieces/core-context';\nimport { mintIdToken } from '@webpieces/gcp-identity';\nimport { LogManager, toError } from '@webpieces/core-util';\nimport { TaskInvoker, TaskRequest, JobReference } from './TaskTypes';\n\nconst log = LogManager.getLogger('InMemoryTaskInvoker');\n\n/**\n * TaskInvoker for tests + local dev — the in-memory-queue twin of GcpTaskInvoker\n * (a TypeScript port of webpieces-java's LocalRemoteInvoker).\n *\n * Instead of enqueuing to Google Cloud Tasks, it drops the delivery onto an in-process\n * timer queue and returns IMMEDIATELY (breaking from the caller, exactly like handing a\n * task to Cloud Tasks). The queued job then delivers the task the SAME way real Cloud\n * Tasks does: a plain HTTP POST to `targetUrl + path` with the JSON body and the\n * synthesized delivery auth (OIDC bearer / shared-secret). It does NOT invoke the server\n * in-process — the target may be a different process entirely — so the request travels\n * over real HTTP (e.g. http://localhost:{port}/queue/path) and is served by the target's\n * real routing + filter chain, giving production parity without GCP.\n *\n * Bind it (via appOverrides) in place of GcpTaskInvoker:\n * bind(TaskInvoker).to(InMemoryTaskInvoker)\n */\n@provideSingleton()\n@injectable()\nexport class InMemoryTaskInvoker extends TaskInvoker {\n private counter = 0;\n /** Scheduled (not-yet-delivered) jobs, so delete() can cancel them. */\n private readonly pending = new Map<string, ReturnType<typeof setTimeout>>();\n\n override async enqueue(request: TaskRequest): Promise<JobReference> {\n this.counter += 1;\n const taskId = request.scheduleInfo.dedupName ?? `inmem-${request.queueName}-${this.counter}`;\n const delayMs = this.computeDelayMs(request.scheduleInfo.epochMsToRunAt);\n\n // Break from the caller: queue the HTTP delivery and return the reference NOW.\n const timer = setTimeout(() => {\n this.pending.delete(taskId);\n void this.deliver(request, taskId);\n }, delayMs);\n // A queued task must not keep the process alive on its own.\n timer.unref?.();\n this.pending.set(taskId, timer);\n\n log.debug(`queued local task ${taskId} -> ${request.targetUrl}${request.path} (delay ${delayMs}ms)`);\n return new JobReference(taskId);\n }\n\n override async delete(ref: JobReference): Promise<void> {\n const timer = this.pending.get(ref.taskId);\n if (timer) {\n clearTimeout(timer);\n this.pending.delete(ref.taskId);\n }\n }\n\n /** ms until the scheduled run time (0 = as soon as possible / already due). */\n private computeDelayMs(epochMsToRunAt?: number): number {\n if (epochMsToRunAt === undefined) {\n return 0;\n }\n const delay = epochMsToRunAt - Date.now();\n return delay > 0 ? delay : 0;\n }\n\n /** Deliver the queued task over real HTTP, mirroring Cloud Tasks' HTTP callback. */\n private async deliver(request: TaskRequest, taskId: string): Promise<void> {\n const url = `${request.targetUrl}${request.path}`;\n const headers = await this.buildHeaders(request);\n log.info(`delivering local task ${taskId}: POST ${url}`);\n // eslint-disable-next-line @webpieces/no-unmanaged-exceptions -- detached queue job: log delivery failure, never crash the queue\n try {\n // webpieces-disable no-fetch -- in-memory queue delivers over real HTTP like Cloud Tasks (no server to invoke in-process)\n const response = await fetch(url, {\n method: 'POST',\n headers: headers,\n body: JSON.stringify(request.body ?? {}),\n });\n if (!response.ok) {\n log.error(`local task ${taskId} delivery to ${url} failed: HTTP ${response.status}`);\n return;\n }\n log.debug(`local task ${taskId} delivered: HTTP ${response.status}`);\n } catch (err: unknown) {\n const error = toError(err);\n log.error(`local task ${taskId} delivery to ${url} threw: ${error.message}`);\n }\n }\n\n /** content-type + propagated context headers + synthesized delivery credential. */\n private async buildHeaders(request: TaskRequest): Promise<Record<string, string>> {\n const headers: Record<string, string> = { 'content-type': 'application/json' };\n for (const entry of request.contextHeaders.entries()) {\n headers[entry[0]] = entry[1];\n }\n await this.attachAuth(request, headers);\n return headers;\n }\n\n /** Synthesize the delivery credential Cloud Tasks would attach, per the auth mode. */\n private async attachAuth(request: TaskRequest, headers: Record<string, string>): Promise<void> {\n const mode = request.authMode;\n if (mode.kind === 'oidc') {\n headers['authorization'] = `Bearer ${await mintIdToken(request.targetUrl)}`;\n return;\n }\n if (mode.kind === 'shared-secret') {\n const secret = process.env[mode.secretEnv];\n if (secret) {\n headers['x-webpieces-shared-secret'] = secret;\n }\n }\n // public / jwt → no service credential is synthesized.\n }\n}\n"]}
1
+ {"version":3,"file":"InMemoryTaskInvoker.js","sourceRoot":"","sources":["../../../../../packages/cloud/cloudtasks-client/src/InMemoryTaskInvoker.ts"],"names":[],"mappings":"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","sourcesContent":["import { injectable } from 'inversify';\nimport { provideFrameworkSingleton } from '@webpieces/core-context';\nimport { mintIdToken } from '@webpieces/gcp-identity';\nimport { LogManager, toError } from '@webpieces/core-util';\nimport { TaskInvoker, TaskRequest, JobReference } from './TaskTypes';\n\nconst log = LogManager.getLogger('InMemoryTaskInvoker');\n\n/**\n * TaskInvoker for tests + local dev — the in-memory-queue twin of GcpTaskInvoker\n * (a TypeScript port of webpieces-java's LocalRemoteInvoker).\n *\n * Instead of enqueuing to Google Cloud Tasks, it drops the delivery onto an in-process\n * timer queue and returns IMMEDIATELY (breaking from the caller, exactly like handing a\n * task to Cloud Tasks). The queued job then delivers the task the SAME way real Cloud\n * Tasks does: a plain HTTP POST to `targetUrl + path` with the JSON body and the\n * synthesized delivery auth (OIDC bearer / shared-secret). It does NOT invoke the server\n * in-process — the target may be a different process entirely — so the request travels\n * over real HTTP (e.g. http://localhost:{port}/queue/path) and is served by the target's\n * real routing + filter chain, giving production parity without GCP.\n *\n * Bind it (via appOverrides) in place of GcpTaskInvoker:\n * bind(TaskInvoker).to(InMemoryTaskInvoker)\n */\n@provideFrameworkSingleton()\n@injectable()\nexport class InMemoryTaskInvoker extends TaskInvoker {\n private counter = 0;\n /** Scheduled (not-yet-delivered) jobs, so delete() can cancel them. */\n private readonly pending = new Map<string, ReturnType<typeof setTimeout>>();\n\n override async enqueue(request: TaskRequest): Promise<JobReference> {\n this.counter += 1;\n const taskId = request.scheduleInfo.dedupName ?? `inmem-${request.queueName}-${this.counter}`;\n const delayMs = this.computeDelayMs(request.scheduleInfo.epochMsToRunAt);\n\n // Break from the caller: queue the HTTP delivery and return the reference NOW.\n const timer = setTimeout(() => {\n this.pending.delete(taskId);\n void this.deliver(request, taskId);\n }, delayMs);\n // A queued task must not keep the process alive on its own.\n timer.unref?.();\n this.pending.set(taskId, timer);\n\n log.debug(`queued local task ${taskId} -> ${request.targetUrl}${request.path} (delay ${delayMs}ms)`);\n return new JobReference(taskId);\n }\n\n override async delete(ref: JobReference): Promise<void> {\n const timer = this.pending.get(ref.taskId);\n if (timer) {\n clearTimeout(timer);\n this.pending.delete(ref.taskId);\n }\n }\n\n /** ms until the scheduled run time (0 = as soon as possible / already due). */\n private computeDelayMs(epochMsToRunAt?: number): number {\n if (epochMsToRunAt === undefined) {\n return 0;\n }\n const delay = epochMsToRunAt - Date.now();\n return delay > 0 ? delay : 0;\n }\n\n /** Deliver the queued task over real HTTP, mirroring Cloud Tasks' HTTP callback. */\n private async deliver(request: TaskRequest, taskId: string): Promise<void> {\n const url = `${request.targetUrl}${request.path}`;\n const headers = await this.buildHeaders(request);\n log.info(`delivering local task ${taskId}: POST ${url}`);\n // eslint-disable-next-line @webpieces/no-unmanaged-exceptions -- detached queue job: log delivery failure, never crash the queue\n try {\n // webpieces-disable no-fetch -- in-memory queue delivers over real HTTP like Cloud Tasks (no server to invoke in-process)\n const response = await fetch(url, {\n method: 'POST',\n headers: headers,\n body: JSON.stringify(request.body ?? {}),\n });\n if (!response.ok) {\n log.error(`local task ${taskId} delivery to ${url} failed: HTTP ${response.status}`);\n return;\n }\n log.debug(`local task ${taskId} delivered: HTTP ${response.status}`);\n } catch (err: unknown) {\n const error = toError(err);\n log.error(`local task ${taskId} delivery to ${url} threw: ${error.message}`);\n }\n }\n\n /** content-type + propagated context headers + synthesized delivery credential. */\n private async buildHeaders(request: TaskRequest): Promise<Record<string, string>> {\n const headers: Record<string, string> = { 'content-type': 'application/json' };\n for (const entry of request.contextHeaders.entries()) {\n headers[entry[0]] = entry[1];\n }\n await this.attachAuth(request, headers);\n return headers;\n }\n\n /** Synthesize the delivery credential Cloud Tasks would attach, per the auth mode. */\n private async attachAuth(request: TaskRequest, headers: Record<string, string>): Promise<void> {\n const mode = request.authMode;\n if (mode.kind === 'oidc') {\n headers['authorization'] = `Bearer ${await mintIdToken(request.targetUrl)}`;\n return;\n }\n if (mode.kind === 'shared-secret') {\n const secret = process.env[mode.secretEnv];\n if (secret) {\n headers['x-webpieces-shared-secret'] = secret;\n }\n }\n // public / jwt → no service credential is synthesized.\n }\n}\n"]}
@@ -39,7 +39,7 @@ let TaskClientCreator = class TaskClientCreator {
39
39
  exports.TaskClientCreator = TaskClientCreator;
40
40
  exports.TaskClientCreator = TaskClientCreator = tslib_1.__decorate([
41
41
  (0, core_util_1.DocumentDesign)(),
42
- (0, core_context_1.provideSingleton)(),
42
+ (0, core_context_1.provideFrameworkSingleton)(),
43
43
  (0, inversify_1.injectable)(),
44
44
  tslib_1.__param(0, (0, inversify_1.inject)(TaskTypes_1.TaskInvoker)),
45
45
  tslib_1.__param(1, (0, inversify_1.inject)(core_util_1.HeaderRegistry)),
@@ -1 +1 @@
1
- {"version":3,"file":"TaskClientCreator.js","sourceRoot":"","sources":["../../../../../packages/cloud/cloudtasks-client/src/TaskClientCreator.ts"],"names":[],"mappings":";;;;AAAA,yCAA+C;AAC/C,0DAA6F;AAC7F,oDAAsE;AACtE,0DAAyD;AACzD,2CAA0C;AAC1C,2DAAyE;AAKzE;;;;;;GAMG;AAII,IAAM,iBAAiB,GAAvB,MAAM,iBAAiB;IAEgB;IACG;IAF7C,YAC0C,OAAoB,EACjB,QAAwB;QAD3B,YAAO,GAAP,OAAO,CAAa;QACjB,aAAQ,GAAR,QAAQ,CAAgB;IAClE,CAAC;IAEJ,gFAAgF;IAChF,qBAAqB,CAAmB,QAAyB,EAAE,WAAmB;QAClF,MAAM,MAAM,GAAG,IAAI,oCAAgB,CAC/B,GAAG,EAAE,CAAC,IAAA,6BAAc,EAAC,WAAW,CAAC,EACjC,IAAI,CAAC,OAAO,EACZ,IAAI,CAAC,eAAe,EAAE,CACzB,CAAC;QACF,OAAO,IAAA,oCAAgB,EAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IAC9C,CAAC;IAED,6DAA6D;IAC7D,iBAAiB,CAAmB,QAAyB,EAAE,GAAW;QACtE,MAAM,MAAM,GAAG,IAAI,oCAAgB,CAAC,GAAG,EAAE,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,eAAe,EAAE,CAAC,CAAC;QAC/E,OAAO,IAAA,oCAAgB,EAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IAC9C,CAAC;IAEO,eAAe;QACnB,OAAO,IAAI,yBAAU,CAAC,IAAI,mCAAoB,EAAE,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;IACrE,CAAC;CACJ,CAAA;AAzBY,8CAAiB;4BAAjB,iBAAiB;IAH7B,IAAA,0BAAc,GAAE;IAChB,IAAA,+BAAgB,GAAE;IAClB,IAAA,sBAAU,GAAE;IAGJ,mBAAA,IAAA,kBAAM,EAAC,uBAAW,CAAC,CAAA;IACnB,mBAAA,IAAA,kBAAM,EAAC,0BAAc,CAAC,CAAA;6CADwB,uBAAW;QACP,0BAAc;GAH5D,iBAAiB,CAyB7B","sourcesContent":["import { inject, injectable } from 'inversify';\nimport { provideSingleton, RequestContextReader, ContextMgr } from '@webpieces/core-context';\nimport { HeaderRegistry, DocumentDesign } from '@webpieces/core-util';\nimport { getCloudRunUrl } from '@webpieces/gcp-identity';\nimport { TaskInvoker } from './TaskTypes';\nimport { createTaskClient, TaskClientConfig } from './TaskClientFactory';\n\n/** Constructor whose prototype is T (the abstract @PubSub API class). */\ntype ApiPrototype<T> = Function & { prototype: T };\n\n/**\n * Injectable factory for Cloud Tasks enqueue clients — the twin of http-client's\n * RpcClientCreator. Resolves the bound TaskInvoker + a context-propagating ContextMgr\n * so a service just asks for a typed client:\n *\n * const emailTasks = creator.createClientOnService(EmailApi, 'email-svc'); // self/other svc\n */\n@DocumentDesign()\n@provideSingleton()\n@injectable()\nexport class TaskClientCreator {\n constructor(\n @inject(TaskInvoker) private readonly invoker: TaskInvoker,\n @inject(HeaderRegistry) private readonly registry: HeaderRegistry,\n ) {}\n\n /** Enqueue client whose delivery URL is another Cloud Run service (by name). */\n createClientOnService<T extends object>(apiClass: ApiPrototype<T>, serviceName: string): T {\n const config = new TaskClientConfig(\n () => getCloudRunUrl(serviceName),\n this.invoker,\n this.buildContextMgr(),\n );\n return createTaskClient(apiClass, config);\n }\n\n /** Enqueue client whose delivery URL is a fixed base URL. */\n createClientOnUrl<T extends object>(apiClass: ApiPrototype<T>, url: string): T {\n const config = new TaskClientConfig(url, this.invoker, this.buildContextMgr());\n return createTaskClient(apiClass, config);\n }\n\n private buildContextMgr(): ContextMgr {\n return new ContextMgr(new RequestContextReader(), this.registry);\n }\n}\n"]}
1
+ {"version":3,"file":"TaskClientCreator.js","sourceRoot":"","sources":["../../../../../packages/cloud/cloudtasks-client/src/TaskClientCreator.ts"],"names":[],"mappings":";;;;AAAA,yCAA+C;AAC/C,0DAAsG;AACtG,oDAAsE;AACtE,0DAAyD;AACzD,2CAA0C;AAC1C,2DAAyE;AAKzE;;;;;;GAMG;AAII,IAAM,iBAAiB,GAAvB,MAAM,iBAAiB;IAEgB;IACG;IAF7C,YAC0C,OAAoB,EACjB,QAAwB;QAD3B,YAAO,GAAP,OAAO,CAAa;QACjB,aAAQ,GAAR,QAAQ,CAAgB;IAClE,CAAC;IAEJ,gFAAgF;IAChF,qBAAqB,CAAmB,QAAyB,EAAE,WAAmB;QAClF,MAAM,MAAM,GAAG,IAAI,oCAAgB,CAC/B,GAAG,EAAE,CAAC,IAAA,6BAAc,EAAC,WAAW,CAAC,EACjC,IAAI,CAAC,OAAO,EACZ,IAAI,CAAC,eAAe,EAAE,CACzB,CAAC;QACF,OAAO,IAAA,oCAAgB,EAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IAC9C,CAAC;IAED,6DAA6D;IAC7D,iBAAiB,CAAmB,QAAyB,EAAE,GAAW;QACtE,MAAM,MAAM,GAAG,IAAI,oCAAgB,CAAC,GAAG,EAAE,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,eAAe,EAAE,CAAC,CAAC;QAC/E,OAAO,IAAA,oCAAgB,EAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IAC9C,CAAC;IAEO,eAAe;QACnB,OAAO,IAAI,yBAAU,CAAC,IAAI,mCAAoB,EAAE,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;IACrE,CAAC;CACJ,CAAA;AAzBY,8CAAiB;4BAAjB,iBAAiB;IAH7B,IAAA,0BAAc,GAAE;IAChB,IAAA,wCAAyB,GAAE;IAC3B,IAAA,sBAAU,GAAE;IAGJ,mBAAA,IAAA,kBAAM,EAAC,uBAAW,CAAC,CAAA;IACnB,mBAAA,IAAA,kBAAM,EAAC,0BAAc,CAAC,CAAA;6CADwB,uBAAW;QACP,0BAAc;GAH5D,iBAAiB,CAyB7B","sourcesContent":["import { inject, injectable } from 'inversify';\nimport { provideFrameworkSingleton, RequestContextReader, ContextMgr } from '@webpieces/core-context';\nimport { HeaderRegistry, DocumentDesign } from '@webpieces/core-util';\nimport { getCloudRunUrl } from '@webpieces/gcp-identity';\nimport { TaskInvoker } from './TaskTypes';\nimport { createTaskClient, TaskClientConfig } from './TaskClientFactory';\n\n/** Constructor whose prototype is T (the abstract @PubSub API class). */\ntype ApiPrototype<T> = Function & { prototype: T };\n\n/**\n * Injectable factory for Cloud Tasks enqueue clients — the twin of http-client's\n * RpcClientCreator. Resolves the bound TaskInvoker + a context-propagating ContextMgr\n * so a service just asks for a typed client:\n *\n * const emailTasks = creator.createClientOnService(EmailApi, 'email-svc'); // self/other svc\n */\n@DocumentDesign()\n@provideFrameworkSingleton()\n@injectable()\nexport class TaskClientCreator {\n constructor(\n @inject(TaskInvoker) private readonly invoker: TaskInvoker,\n @inject(HeaderRegistry) private readonly registry: HeaderRegistry,\n ) {}\n\n /** Enqueue client whose delivery URL is another Cloud Run service (by name). */\n createClientOnService<T extends object>(apiClass: ApiPrototype<T>, serviceName: string): T {\n const config = new TaskClientConfig(\n () => getCloudRunUrl(serviceName),\n this.invoker,\n this.buildContextMgr(),\n );\n return createTaskClient(apiClass, config);\n }\n\n /** Enqueue client whose delivery URL is a fixed base URL. */\n createClientOnUrl<T extends object>(apiClass: ApiPrototype<T>, url: string): T {\n const config = new TaskClientConfig(url, this.invoker, this.buildContextMgr());\n return createTaskClient(apiClass, config);\n }\n\n private buildContextMgr(): ContextMgr {\n return new ContextMgr(new RequestContextReader(), this.registry);\n }\n}\n"]}