get-convex / get-convex/r2

deleteObject: expose a delete whose completion can be awaited

Open
#81 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
TypeScript
Stars
49
Forks
26
Avg merge
6h 22m
Merged PRs (30d)
1

Description

Title: deleteObject: expose a delete whose completion can be awaited

`r2.deleteObject(ctx, key)` removes the metadata row in the calling mutation's transaction, but the actual S3 `DeleteObject` runs later through the component's internal action retrier. The caller gets no handle to that work: when `deleteObject` returns, the bytes may still exist — and if the retrier ultimately gives up, they exist forever, with nothing upstream ever hearing about it.

For most callers that's fine. It bites when the caller must *prove* deletion — legal erasure, tenant teardown — where "my delete calls returned" is not evidence the bytes are gone. We hit this in production tooling: a teardown reported `complete: true` while deletes were still retrying (and our test suite independently flaked on the same hidden asynchrony — the scheduled retries outliving the test's timer budget).

Our current workaround wires a separate `@convex-dev/action-retrier` around the component's internals — calling `components.r2.lib.deleteMetadata` and `components.r2.lib.deleteR2Object` directly with `r2.config` — so the caller gets a run id it can await and a failure it can surface. It works, but it reaches into private API and duplicates a retrier the component already contains.

Ask: a supported form of the same thing, in whatever shape fits the component's design, e.g.:

- `deleteObject` returning a handle/run id whose status can be polled, or
- an `awaitDelete`/`onComplete` option, or
- a queryable status for a key's pending delete.

Happy to share our workaround or test setup if useful. Thanks for the component!

Contributor guide

Open the contributing guide

Research direction

Start at the public `r2.deleteObject` entry point and trace the internal action retrier, including the `components.r2.lib.deleteMetadata` and `components.r2.lib.deleteR2Object` calls described here. Compare that flow with the workaround's run-id and status handling; done means a supported API lets callers await completion and surface terminal failure, with coverage for retry timing.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
backend-api-design, cloud
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Needs clarification
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.