Skip to content

feat(taskqueue): route PushQueue to Cloud Tasks v2 (GA) - #118

Open
riddhi-shivhare wants to merge 2 commits into
GoogleCloudPlatform:masterfrom
riddhi-shivhare:taskqueue-v2-ga
Open

riddhi-shivhare wants to merge 2 commits into
GoogleCloudPlatform:masterfrom
riddhi-shivhare:taskqueue-v2-ga

Conversation

@riddhi-shivhare

Copy link
Copy Markdown

When APPENGINE_USE_CLOUDTASK_PUSH_QUEUE is enabled, PushTask::add() and PushQueue::addTasks() are served by the Cloud Tasks v2 CloudTasksClient instead of the legacy TaskQueue API:

  • A single task uses createTask.
  • Multiple tasks use batchCreateTasks. Created task names are read from the operation result, and failedRequests in the operation metadata are mapped back to TaskQueue exceptions.
  • Sub-second delays are preserved in the schedule time.
  • ALREADY_EXISTS maps to TaskAlreadyExistsException. NOT_FOUND is not treated as an existing task.
  • One client is used for all tasks in a call.

Adds google/cloud-tasks (^2.3) to composer.json suggest, pins php-coveralls to ^2.7 for PHP 7.2-8.2 CI, and adds unit tests in tests/Api/TaskQueue/PushQueueTest.php.

@riddhi-shivhare
riddhi-shivhare force-pushed the taskqueue-v2-ga branch 2 times, most recently from 21029b3 to edbe841 Compare October 7, 2026 20:13
Comment thread src/Api/TaskQueue/PushQueue.php Outdated
Comment thread src/Api/TaskQueue/PushQueue.php Outdated
* Upper bound on waiting for a Cloud Tasks batch operation. Cloud Tasks
* normally returns batch operations already done.
*/
const CLOUD_TASKS_OPERATION_TIMEOUT_MILLIS = 30000;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why we need this? You already know that the batch operations are sync only.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed.

Comment thread src/Api/TaskQueue/PushQueue.php Outdated
$host = substr($host, 0, (int) strrpos($host, '.'));
}
$parts = explode('.', str_replace('-dot-', '.', $host));
array_pop($parts); // The app ID.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verify that the extracted application identifier matches self::getProjectId(); if it does not match, break out of the loop and return [getenv('GAE_SERVICE') ?: null, getenv('GAE_VERSION') ?: null, null].

Domain-scoped project IDs (example.com:my-app -> my-app.example.com.appspot.com) also leave example in $parts, misrouting the task.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated buildCloudTaskRouting to verify that the hostname suffix matches self::getProjectId(), falling back to the current GAE_SERVICE and GAE_VERSION when it does not match. Also mapped domain-scoped project IDs (example.com:my-app to my-app.example.com) before stripping the app suffix and added unit test coverage.

$region = self::getRegion();
$fullQueueName = "projects/" . $projectId . "/locations/" . $region . "/queues/" . $this->name;

if (count($tasks) === 1) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

addTasksCloudTasks() assumes $tasks is a zero-indexed sequential array (0 .. n-1). In PHP, callers frequently pass filtered arrays (such as array_filter(...), which preserves non-zero keys like [1 => $task]) or string-keyed arrays, both of which pass is_array($tasks). When count($tasks) === 1 with a non-zero key, $tasks[0] evaluates to null and causes a fatal error in createSingleTaskCloudTasks(). When count($tasks) > 1, $createTaskRequests is zero-indexed while processBatchCreateResponse() looks up $failedRequests[$idx] using the original keys from $tasks, silently ignoring per-task failures. Normalise $tasks = array_values($tasks); at the entry to addTasks().

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Normalized $tasks with array_values($tasks) at the start of addTasks() and added unit test coverage for non-zero-indexed arrays in both single and batch paths.

Comment thread src/Api/TaskQueue/PushQueue.php Outdated

$ownsClient = ($client === null);
if ($ownsClient) {
$client = self::newCloudTasksClient($clientClass);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Every single-task PushTask::add() call instantiates a new CloudTasksClient and closes its transport in finally. In google/gax, constructing and closing a client per call re-initialises channel credentials, middleware stacks, and transport connections on every enqueue, adding substantial latency when enqueuing multiple individual tasks within a single request. Cache and reuse a lazy static client instance per request (resetting the cached instance when setCloudTasksClientFactory() is called).

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated getCloudTasksClient() to lazily cache and reuse a static CloudTasksClient instance across calls within a request, and updated setCloudTasksClientFactory() to close and reset the cached client.

Comment thread src/Api/TaskQueue/PushQueue.php Outdated
}
// The fallback is not cached, so a failed metadata server request (for
// example a timeout during a cold start) is retried on the next call.
return getenv('LOCAL_GCP_REGION') ?: 'us-central1';

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you check whether it is us-central1 or just us-central. Test this first, as I remember GAE has us-central only.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tested live against Cloud Tasks v2 on rshivhare-demo1 — locations/us-central1 succeeds while locations/us-central fails with 400 INVALID_ARGUMENT: Location 'us-central' is not a valid location. Kept 'us-central1' and added normalizeRegion to map legacy GAE location strings (us-central -> us-central1, europe-west -> europe-west1).

@riddhi-shivhare
riddhi-shivhare force-pushed the taskqueue-v2-ga branch 5 times, most recently from 0a0ede8 to 8011fde Compare October 8, 2026 07:47
When APPENGINE_USE_CLOUDTASK_PUSH_QUEUE is enabled, PushTask::add() and
PushQueue::addTasks() are served by the Cloud Tasks v2 CloudTasksClient
instead of the legacy TaskQueue API. The flag is enabled by "true"
(case-insensitive) or "1".

- A single task uses createTask.
- Multiple tasks use batchCreateTasks. Created task names are read from
  the operation result, and failedRequests in the operation metadata
  are mapped back to TaskQueue exceptions.
- Sub-second delays are preserved in the schedule time.
- ALREADY_EXISTS maps to TaskAlreadyExistsException. NOT_FOUND is not
  treated as an existing task. DEADLINE_EXCEEDED, RESOURCE_EXHAUSTED,
  ABORTED and UNAVAILABLE map to TransientTaskQueueException.
- A Host header that is a hostname of the app sets the task's App Engine
  routing ([[instance.]version.]service). Without one, a task runs on the
  current service and version, like a legacy push task without a target.
- Host, X-Google-* and X-AppEngine-* headers are not sent, since Cloud
  Tasks sets them itself.
- Batch statuses given as arrays or with string codes are handled.
- If batchCreateTasks is not available, tasks are created one at a time
  and every task is attempted, like BulkAdd.
- A region fallback after a failed metadata server request is not cached.
- One client is used for all tasks in a call.

Adds google/cloud-tasks (^2.3) to composer.json suggest, pins
php-coveralls to ^2.7 for PHP 7.2-8.2 CI, and adds unit tests in
tests/Api/TaskQueue/PushQueueTest.php.

@gajjarc gajjarc left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, lets wait for the tiny launch doc approval and have the public doc cl ready. Then we can safely merge.

This branch has not been deployed

No deployments
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.

2 participants