Skip to content

feat(slides): extend the persisted batch primitive to Slides (presentations.batchUpdate) — 197 write calls to rebuild one 7-slide deck, 429s at 60/min #1097

Description

@sebsnyk

What already exists

gog batch is a complete persisted-batch facility: begin, list, show, end, abort, prune, plus --batch=<id> on docs write, docs insert, docs update, docs delete, docs format, docs cell-style, docs table-column-width, docs insert-image and docs insert-person. Open a batch against a document, accumulate requests across many CLI invocations, submit once as a single documents.batchUpdate.

It is Docs-only. On v0.39.0 gog batch begin accepts --doc and --name and nothing else, and no gog slides command carries --batch.

Why Slides needs it more than Docs did

Docs has docs write --replace --markdown, which renders a whole document body in one internal batchUpdate. Slides has no equivalent for shapes. create-from-markdown builds text on the default theme only, and there is no way to place a positioned shape, a coloured panel, a flow box or a native table from a source file. So any deck built with real structure is built element by element, and every gog slides mutation is its own process and its own presentations.batchUpdate carrying a single request.

Two properties of the current command surface multiply the count:

  • element create-shape carries no fill or outline flags, so every shape costs create-shape plus element style.
  • table cell style styles exactly one zero-based cell. There is no row, column or span selector, so an N-by-M table costs N×M style calls on top of N×M insert-text calls.

Measured cost

Rebuilding a seven-slide deck from a source file, a routine shape-heavy deck with two tables, one flow row, a caption band, a chat sequence and seven panels, issues 205 gog slides invocations: 8 raw reads and 197 writes. Per primitive, writes only:

Primitive Writes Composition
Titles and lead lines across 7 slides 23 insert-text per placeholder plus one style-text per run
Native table, 6 rows x 2 cols 29 1 delete of the previous table, 1 table create, 1 element transform, 2 table column size, 12 insert-text, 12 table cell style
Native table, 5 rows x 2 cols 25 same shape
Flow row, 5 boxes and 4 arrow connectors 37 9 deletes, 18 create-shape/style pairs, 5 texts, 5 style runs
Chat sequence, 6 bubbles 36 6 deletes, 6 create-shape/style pairs, 6 texts, 12 style runs
Panel row, 4 panels 24 4 deletes, 4 create-shape/style pairs, 4 texts, 8 style runs
Panel row, 3 panels 18 same shape
Caption band 5 1 delete, create-shape, style, insert-text, style-text

The documented Slides quota is 60 write requests per minute per user per project (https://developers.google.com/workspace/slides/api/limits). 197 writes is 3.3x that ceiling, and because each invocation is a full process plus a round trip the run paces itself at roughly the quota rate. The rebuild fails partway through the fifth slide with:

429 rateLimitExceeded: Quota exceeded for quota metric 'Write requests' and limit
'Write requests per minute per user' of service 'slides.googleapis.com'

Batched, the same deck is one presentations.batchUpdate of 197 requests, well inside the 500-request cap. One quota item instead of 197, and seconds instead of minutes.

What a caller has to do today

Sleep between calls and hope, or drop out of gog entirely and drive presentations.batchUpdate from a Google API client library. The second is what happens in practice, which loses gog's auth handling for the sake of one endpoint.

Proposed surface

Keep the Docs shape verbatim, since consistency with a shipped command is easier to reason about than a new design:

gog batch begin --presentation=<id> [--name=<label>]
gog slides element create-shape  --batch=<id> ...
gog slides element style         --batch=<id> ...
gog slides insert-text           --batch=<id> ...
gog slides style-text            --batch=<id> ...
gog slides table create          --batch=<id> ...
gog slides table cell style      --batch=<id> ...
gog slides table column size     --batch=<id> ...
gog slides element transform     --batch=<id> ...
gog slides element delete        --batch=<id> ...
gog batch end <id>

--dry-run, --continue-on-error, --auto-split and the revision lock behave as they do for Docs. presentations.batchUpdate is atomic in the same way documents.batchUpdate is, so strict-atomic-by-default carries over.

One Slides-specific note worth encoding: a request that creates an object with an explicit objectId and a later request that references that id can sit in the same batch, so a create-then-style pair batches cleanly. Object ids must be at least 5 characters and are unique across the whole presentation, so a batch built from per-slide commands needs no id rewriting.

Commands that should stay out of a batch: raw, read-slide, locate, list-slides, info and thumbnail are reads, and insert-image uploads bytes before it emits a request.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Normal priority bug or improvement with limited blast radius.clawsweeper:needs-maintainer-reviewClawSweeper marked this issue as needing maintainer review before automation.clawsweeper:needs-product-decisionClawSweeper marked this issue as needing a product or behavior decision.clawsweeper:no-new-fix-prClawSweeper does not recommend queueing a new automated fix PR for this issue.impact:otherThis issue has meaningful maintainer-visible impact outside the owned taxonomy.issue-rating: 🌊 off-meta tidepoolIssue quality rating does not apply to this item.

    Type

    No type

    Fields

    Priority

    None yet

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions