Commit Graph
8 Commits
Author SHA1 Message Date
yusufipk 80ef29f787 fix(scripts): tell an empty cleanup scan apart from an unreachable one
The cleanup printed one number for expired owners, the count of
workspaces it found, so zero meant either that nobody had passed the
grace period or that everyone who had owns nothing. The first is normal
and the second means media is held alive by rows the cleanup cannot
reach, and telling them apart took a hand-written query against
production. Both counts are reported now.

Bunny and R2 results were also discarded. The workspace row is deleted
first, so a refused storage delete leaves media that nothing points at,
and nothing recorded that it happened. logCleanupWarnings already exists
for this and is now called with the per-workspace result.
2026-07-30 19:26:06 +07:00
yusufipk 4e60b61edb fix(scripts): count a Bunny id referenced by url, not only by column
A Bunny guid is stored twice per row: in `VideoVersion.videoId` and
`VideoAsset.providerVideoId` on its own, and inside `originalUrl` / `sourceUrl`
as `https://iframe.mediadelivery.net/embed/<library>/<guid>`. The lookup read
only the id columns.

They are written together so they normally agree, but this query decides what
gets deleted. A row whose id column was left empty or drifted while its url
still carried the guid would present a live video as an orphan, and the script
would delete media the product is still serving. Reading both makes a
disagreement harmless instead of destructive.

Bunny rows are now read in one pass rather than filtered per candidate id: the
url match is a substring test, and there are only as many of these rows as there
are Bunny videos in the product, so one small scan beats a LIKE per id.
2026-07-26 19:24:13 +07:00
yusufipk 1f7b77873c fix(scripts): make the orphan cleanups reviewable before they delete
Two problems with running these unattended, both found while wiring the Bunny
cleanup up to a Coolify scheduled task against production.

A dry run reported a count and nothing else. "Orphaned: 31" is not something
anyone can approve: it says how many objects would go, never which. Both scripts
now list every orphan they would delete, and print the same list when deleting,
so a real run is auditable afterwards too.

Each line carries who the object belongs to, as far as each provider can answer:

- R2 reads the owner out of `videoUploadSession`, which keeps `objectKey`
  alongside the initiating and billed user and survives an upload that never
  became a video. That is the case producing orphans, so this is an answer
  rather than a guess.
- Bunny has no equivalent. `bunny-init` sends the provider a title and nothing
  else, and an orphan by definition has no row pointing at it, so there is
  nothing authoritative to look up. The title is matched against titles still in
  the database instead, which catches the common shape (a version upload that
  failed and was retried successfully leaves a live row with the same title).
  A hit prints as "possibly", because it is a hint.

The grace periods were also too short to be safe:

- Bunny counted a video abandoned after 24 hours.
- R2 counted an object abandoned after 15 minutes, which is shorter than a slow
  multipart upload of a large file. An object still being written, or written
  but not yet finalised into a row, looked abandoned and could be deleted out
  from under the upload creating it.

Both are seven days now: long enough that no upload, retry or delayed
finalisation can still be in flight.
2026-07-26 19:08:03 +07:00
Enes Köksal 3cfea40fbd refactor: eslint and prettier conflict will be resolved and formatted 2026-04-23 17:05:43 +03:00
Yusuf İpek 8014fc3986 Refactor error logging across the application to use a centralized logger
- Introduced a new logger utility (`logError`) to standardize error logging.
- Replaced all instances of `console.error` with `logError` in various API routes and libraries.
- Enhanced error logging to sanitize sensitive information, particularly for Prisma and Stripe errors.
- Ensured consistent error handling and logging practices throughout the codebase.
2026-04-10 21:10:09 +03:00
Yusuf İpek 6f22b0bf8b feat(billing): integrate Stripe for subscription management and billing access
- Added billing-related fields to the User model in the database.
- Implemented functions for managing billing access, including trial periods and subscription statuses.
- Created new billing utility functions for Stripe integration.
- Updated onboarding page to include billing overview and workspace creation eligibility.
- Enhanced route access checks to require billing access for certain actions.
- Implemented cleanup scripts for expired billing workspaces and associated media.
- Updated header component to conditionally show app navigation based on billing access.
- Added new migrations for billing-related database changes.
2026-04-08 17:50:40 +03:00
Yusuf İpek 9ce033d306 feat(video-assets): add full video asset system (uploads, downloads, @mentions, and cleanup/billing integration) 2026-02-25 18:34:03 +03:00
Yusuf İpek fa51847aa4 feat(storage): add shared R2 media proxy and orphan cleanup tooling for R2/Bunny 2026-02-24 17:02:54 +03:00