Skip to content

feat(adapters): google-cloudtasks-style — full Cloud Tasks v2 surface - #99

Merged
deblasis merged 2 commits into
mainfrom
feat/google-cloudtasks-style-adapter
Aug 23, 2026
Merged

feat(adapters): google-cloudtasks-style — full Cloud Tasks v2 surface#99
deblasis merged 2 commits into
mainfrom
feat/google-cloudtasks-style-adapter

Conversation

@deblasis

Copy link
Copy Markdown
Contributor

What

A new reference adapter simulating the Google Cloud Tasks API (cloudtasks.googleapis.com/v2, REST), covering the full documented v2 surface — 16 endpoints across three resources.

Surface

projects.locationsget, list (canonical GCP region set, pageSize/pageToken), getCmekConfig/updateCemekConfig ({name, kmsKey}).

queuescreate (queueId query param or name-derived; service defaults for rateLimits/retryConfig; derived output-only maxBurstSize; caps enforced), get, list (lexicographic, pageSize ≤ 9800, name/state filter subset with =/!=/:), patch (AIP-134 updateMask: bare path replaces the message, dotted path sets a leaf; state rejected), delete (cascades to tasks), :pause/:resume (idempotent), :purge (deletes tasks created before the purge moment, stamps purgeTime), :getIamPolicy/:setIamPolicy (etag-checked → 409 ABORTED)/:testIamPermissions.

taskscreate (exactly-one-of httpRequest/appEngineHttpRequest, URL scheme, body-vs-method, relativeUri, ID charset, past scheduleTime clamped, task de-duplication incl. 24h tombstones for deleted/executed names), get/list/delete, :run (ignores scheduleTime/queue state/rate limits; returns post-dispatch status, then completes and deletes the task — re-runs 404 like the real API), :buffer (both forms; URL assembled from the queue httpTarget uriOverride).

Views: BASIC (default) omits request bodies; FULL returns everything. Errors are the canonical {"error": {code, message, status}} envelope (INVALID_ARGUMENT / NOT_FOUND / ALREADY_EXISTS / ABORTED / UNAUTHENTICATED). Malformed JSON gets the real API's "Invalid JSON payload received.".

Authored profile

failing-workertasks.run models a worker answering HTTP 500: the attempt is recorded (responseStatus, counters) and the task reschedules per the queue's retryConfig (min/max backoff, doublings; maxAttempts and maxRetryDuration exhaustion → permanent failure + tombstone). Deterministic retry/backoff path for clients, same pattern as sqs-style's throttled.

Tests & verification

  • 16 VM tests over a shared store and virtual clock (no sleeps): validations, defaults, patch masks, pagination, views, tombstone lifecycle (incl. 24h expiry), run success/failure paths, buffer, purge, IAM etag flow, cascade, auth.
  • Live-booted and exercised end-to-end over HTTP (transcripts in the adapter README); the failing-worker profile driven through the dashboard profile API.
  • go test ./..., gofmt -l, go vet clean; adapter lint clean; boot + parse QC guards pass (99 adapters).
  • Conformance matrix entry (curated deviations/missing), CONFORMANCE.md + README.md count regenerated (99).

New reference adapter simulating the Google Cloud Tasks API (v2 REST):
- locations: get/list, cmekConfig get/update
- queues: create/get/list/patch/delete, :pause/:resume/:purge, IAM trio
  (etag-checked setIamPolicy), name/state filter subset, updateMask
  semantics (bare path replaces, dotted path sets a leaf)
- tasks: create (full validation incl. body-vs-method, url scheme,
  de-duplication with 24h tombstones), get/list/delete, :run (post-dispatch
  status then completion), :buffer (generated and caller-chosen IDs, URL
  built from queue httpTarget uriOverride)
- Service defaults for rateLimits/retryConfig on create; derived
  maxBurstSize; BASIC/FULL response views
- Authored profile failing-worker: tasks.run records a 500 and reschedules
  per the queue's retryConfig (doubling curve, maxAttempts and
  maxRetryDuration exhaustion) — deterministic retry/backoff testing
- VM test suite over a virtual clock (16 tests); conformance matrix entry
  (99 adapters)
…styped fields

Review follow-up: every client-supplied field that reaches arithmetic or
slicing is now type-checked (null = proto-JSON absent, wrong type = 400
INVALID_ARGUMENT, never a handler 500): queue/task names, scheduleTime,
httpRequest.url, relativeUri, rateLimits/retryConfig/httpTarget object
shapes (validated at queue write so tasks:buffer can never trip on stored
state), CMEK kmsKey.

Also: uriOverride.port renders as an integer (8080, not 8080.0 — the
value round-trips through the store as a float), port <= 0 clears it;
tests pin the exact virtual-clock retry schedule (+10s, +30s) instead of
directional checks, assert the previously-vacuous first create, and cover
the adversarial matrix plus port rendering.
@deblasis
deblasis merged commit bb34290 into main Aug 23, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant