Commit Graph

13027 Commits (feat/emoji-cloud-storage-v2)
 

Author SHA1 Message Date
Your Name e5c119d35c revert: run emoji cloud migration inline, not via queued job
Keep the migration running the upload inline (Artisan::call), not dispatched
to the queue. The local emoji files live on the web container's storage where
migrations run; a queued Horizon worker may not share that storage in future
(web and horizon storage decoupled), which would make a queued job a no-op.

Reverts the EmojiMigrateToCloudPipeline job approach.
3 weeks ago
Your Name 808a03117d refactor: run emoji cloud migration as a queued job, not inline in migrate
Running the ~25k-file S3 upload synchronously via Artisan::call inside the
migration blocked the upgrade with no visible output, and a mid-run failure
would leave the migration in a bad state.

Dispatch EmojiMigrateToCloudPipeline (ShouldQueue, ShouldBeUnique) onto the
mmo queue instead, so migrate returns immediately and the upload runs in the
background on Horizon. The job re-checks the cloud-storage guard at runtime,
runs the async command (--concurrency=100), has a 1h timeout and tries=1,
and is unique so it can't stack up.
3 weeks ago
Your Name 186f62fff9 change: admin:resyncemoji takes a required list of filenames
Instead of scanning all emoji, target specific files by name:
  admin:resyncemoji "26109.png,1234.gif"

Looks up each by media_path (emoji/{filename}), and for found remote emoji
re-downloads from image_remote_url onto the active disk. Reports per-file
status (resynced/skipped/failed/not_found). --missingonly still guards each
against the disk so present files are left alone; --dry-run and --force.
3 weeks ago
Your Name 5764c135f5 feat: add admin:resyncemoji to re-download remote emoji from origin
Re-fetches remote custom emoji media from image_remote_url (SSRF-hardened via
SecureMediaFetchService) and stores it on the active disk. Useful to repair
emoji whose stored file went missing.

- --missingonly checks each emoji's file on the active disk (cloud when cloud
  storage is enabled) and only re-downloads the ones that are absent
- --dry-run, --limit, --force
- CustomEmojiService::resync() does the per-emoji fetch+store; CustomEmoji
  gains a mediaExists() helper
3 weeks ago
Your Name fdd6c4211d fix: correct async upload result-to-file mapping in emoji migration
CommandPool re-indexes promises by default, so the key passed to the
fulfilled/rejected callbacks did not reliably map back to $files[$key] on
out-of-order async completions. This mismapped results to the wrong file and
could delete a local copy whose upload belonged to (or failed for) a
different file, leaving gaps on cloud (404s).

Key the command generator by the local path and set preserve_iterator_keys
so callbacks receive the exact path they correspond to. No more index math.
3 weeks ago
Your Name 982cafd7f6 feat: emoji cloud storage with async S3 migration command
Re-land the emoji cloud-storage work on a clean staging base, using the
async AWS SDK upload path.

- CustomEmoji model: cloud-aware URL + storage helpers (urlForPath, url,
  storageTarget, storeMedia, storeMediaFromFile, deleteMedia)
- Route emoji writes/deletes/URLs through the model in ImportEmojis,
  CustomEmojiService and AdminController; admin views use $emoji->url()
- admin:EmojiMoveStorageLocalToCloud: disk-driven migration using the AWS
  SDK CommandPool with --concurrency (default 100) for high throughput;
  skips missing.png; --dry-run/--keep-local/--offset/--limit/--no-acl/--debug
- Deploy migration + daily schedule under the cloud-storage conditional
3 weeks ago
Shlee 00670aa3a8
Merge pull request #6971 from pixelfed/revert/emoji-cloud-storage
revert: remove emoji local-to-cloud storage changes
3 weeks ago
Your Name 40b323bca4 revert: remove emoji local-to-cloud storage changes
Back out all emoji cloud-storage work from staging so it can be reworked and
re-landed separately (the URL resolution flips to cloud on a global config
flag, which created a broken-URL window, and the migration approach needs
revisiting).

Reverts to pre-emoji state:
- CustomEmoji model URL/storage helpers (urlForPath, storageTarget, storeMedia,
  storeMediaFromFile, deleteMedia, url) and callers in ImportEmojis,
  CustomEmojiService, AdminController
- admin custom-emoji blade views back to local /storage URLs
- Remove admin:EmojiMoveStorageLocalToCloud command
- Remove the deploy migration and its scheduler entry

Media (and the already-reverted story) scheduler entries are untouched.
3 weeks ago
Shlee 18da037181
Merge pull request #6970 from pixelfed/shleeable-patch-1
Update EmojiMoveStorageLocalToCloud.php
3 weeks ago
Shlee 948da00f0c
Update EmojiMoveStorageLocalToCloud.php 3 weeks ago
Shlee ef8cf16cfa
Merge pull request #6968 from pixelfed/debug/emoji-cloud-migration
perf: async S3 SDK upload path for emoji migration
3 weeks ago
Your Name a0a262f07f perf: async S3 SDK upload path for emoji migration
Process-level workers plateaued at ~7.5 uploads/sec against Fastly Object
Storage because each PUT is high-latency and only a handful ran concurrently.

Add --concurrency=N which uses the AWS SDK CommandPool to keep N PutObject
requests in flight from a single process. A successful PutObject response is
the confirmation (no separate HEAD verify), and the local file is deleted on
success. Commands are yielded lazily so memory stays flat over large runs.

--no-acl escape hatch for S3-compatible stores that reject the ACL header.
3 weeks ago
Shlee 2c0fe5db2f
Merge pull request #6967 from pixelfed/debug/emoji-cloud-migration
feat: add uploads/sec throughput counter to emoji migration
3 weeks ago
Your Name f17a88e16c feat: add uploads/sec throughput counter to emoji migration
- Live 'up/s' rate shown on the progress bar during single-worker runs
- Final summary reports elapsed time and uploads/sec
- Parallel runs tally moved across workers and report aggregate uploads/sec

Makes it easy to compare --workers counts and decide whether async S3
(option 2) is worth pursuing.
3 weeks ago
Shlee 67ae799cb4
Merge pull request #6966 from pixelfed/debug/emoji-cloud-migration
perf: parallelise emoji cloud migration with worker processes
3 weeks ago
Your Name 00564ac221 perf: parallelise emoji cloud migration with worker processes
The migration was ~1-2s/file due to sequential S3 round-trips (HEAD + PUT +
verify HEAD). Speed it up:

- --workers=N spawns N child processes, each handling a strided slice of the
  files (index % N == shard) for real concurrency on the I/O-bound uploads
- --skip-cloud-check skips the upfront HEAD (always upload, idempotent)
- --skip-verify skips the post-upload size re-check
- --offset for manual chunking

Storage/Flysystem has no batch or async upload API, so process-level
concurrency is the pragmatic lever here.
3 weeks ago
Shlee b6e8571009
Merge pull request #6965 from pixelfed/debug/emoji-cloud-migration
fix: skip missing.png in emoji cloud migration
3 weeks ago
Your Name 9e5fcb9a90 fix: skip missing.png in emoji cloud migration
The frontend renders a hardcoded /storage/emoji/missing.png local onerror
fallback for emoji, so that placeholder must stay on local disk. Skip it in
the migration so it is never moved to cloud or deleted locally.
3 weeks ago
Shlee e79d5c828b
Merge pull request #6964 from pixelfed/debug/emoji-cloud-migration
fix: make emoji cloud migration disk-driven + add --debug
3 weeks ago
Your Name 79eef56be0 fix: make emoji cloud migration disk-driven + add --debug
The migration was DB-driven (whereNull('uri')), which excluded federated
emoji whose media is stored locally but have a uri set -> the disk was never
scanned, resulting in moved=0.

- Drive the migration by enumerating local files under public/emoji/ instead
  of a DB query; the local file is the source of truth for what needs moving
- Add --debug to print config, custom_emoji table breakdown, local emoji dir
  contents, and per-file decisions
3 weeks ago
Shlee e09297914c
Merge pull request #6963 from pixelfed/revert/story-cloud-migration
revert: story cloud-migration work
3 weeks ago
Your Name 9f55f7204c revert: story cloud-migration work
Back out the story local->cloud migration so we can land and verify the
emoji cloud work first, one change at a time.

Reverts:
- 9f110bb74 feat: migrate local story media to cloud storage
- 842681b99 fix: schedule StoryMoveStorageLocalToCloud command

Removes StoryMoveStorageLocalToCloud command, its scheduler entry, and the
StoryExpire explicit-disk changes. Remcache and emoji work are untouched.
Will revisit story once emoji is confirmed.
3 weeks ago
Shlee 6e73fd4877
Merge pull request #6962 from pixelfed/fix/emoji-cloud-url-and-guard
fix: emoji admin URLs and cloud-migration guard
3 weeks ago
Your Name aa9bb868dd fix: emoji admin URLs and cloud-migration guard
Two issues prevented emoji from serving/migrating correctly on cloud:

- Admin custom-emoji views hardcoded url('storage/'.media_path), so they
  always showed local URLs and bypassed cloud resolution. Use $emoji->url().
- The migration/command guard relied solely on config_cache('pixelfed.cloud_storage'),
  which is DB/12h-cached and can read stale-false right after cloud is
  enabled, causing the migration to silently no-op. Treat cloud as enabled
  when either live config() or config_cache() is true.
3 weeks ago
Shlee 53b3dbfe47
Merge pull request #6961 from pixelfed/fix/story-cloud-schedule
fix: schedule StoryMoveStorageLocalToCloud command
3 weeks ago
Your Name 842681b99b fix: schedule StoryMoveStorageLocalToCloud command
The story cloud-migration command was merged (#6958) but its scheduler
entry was dropped when the emoji branch (based off staging before that
merge) later merged and overwrote the scheduler block. Restore the hourly
schedule so local story media is migrated to cloud automatically.
3 weeks ago
Shlee dd007e2345
Merge pull request #6960 from pixelfed/feat/emoji-cloud-storage
Feat/emoji cloud storage
4 weeks ago
Your Name a945efbf74 feat: add migration to move local emoji to cloud on deploy
Runs admin:EmojiMoveStorageLocalToCloud during migrate so existing local
emoji are relocated to cloud as part of the upgrade, shrinking the window
where emoji URLs resolve to cloud before the files are there. No-op unless
cloud storage is enabled.
4 weeks ago
Your Name 979df6e39e feat: migrate all local emoji to cloud in one pass by default
Change --limit default to 0 (no limit) so the emoji migration processes
every local emoji in a single run instead of capping at 1000, and drop the
limit from the scheduled invocation. Avoids a multi-run window where
not-yet-migrated emoji resolve to missing cloud URLs.
4 weeks ago
Shlee fd39008677
Merge pull request #6959 from pixelfed/feat/emoji-cloud-storage
feat: store custom emoji on cloud storage when enabled
4 weeks ago
Your Name fa76e1014a feat: store custom emoji on cloud storage when enabled
Custom emoji were always written locally and served via hardcoded /storage
URLs, so they never used S3 even on cloud instances.

- CustomEmoji: centralize URL + storage on the active disk (cloud when
  pixelfed.cloud_storage is enabled, else local public/ disk) via
  urlForPath/url/storageTarget/storeMedia/storeMediaFromFile/deleteMedia
- Route emoji writes/deletes and URL generation (scan, CustomEmojiService::all)
  through those helpers in ImportEmojis, CustomEmojiService::import and
  AdminController
- Add admin:EmojiMoveStorageLocalToCloud to migrate existing local emoji to
  cloud: copy, verify by size, delete local, bust caches
- Schedule it daily when cloud storage is enabled
4 weeks ago
Shlee eae6253731
Merge pull request #6958 from pixelfed/fix/remcache-tmp-file-leak
feat: migrate local story media to cloud storage
4 weeks ago
Your Name 9f110bb74c feat: migrate local story media to cloud storage
Ensure story media lands on and stays on cloud storage for S3 instances.

- StoryExpire: archive expiring story media on the same explicit disk the
  media lives on (S3 move is a server-side copy+delete), with error handling
- Add admin:StoryMoveStorageLocalToCloud to migrate local story media
  (active + story_archives) to cloud: copy, verify by size, then delete local
- --orphans option relocates untracked story_archives/ files to cloud using
  the same copy/verify/delete flow (media is moved, never discarded)
- Schedule it hourly alongside the media migration when cloud storage is on
4 weeks ago
Shlee ec1c778c97
Merge pull request #6957 from pixelfed/fix/remcache-tmp-file-leak
Fix/remcache tmp file leak
4 weeks ago
Your Name 9704fd5a36 refactor: use GarbageCollector prefix for GC console command classes
Rename the internal garbage collector commands to a consistent
GarbageCollector* naming scheme (file + class). Command signatures are
unchanged, so the scheduler and cron entries are unaffected.

- MediaGarbageCollector          -> GarbageCollectorMedia
- DatabaseSessionGarbageCollector -> GarbageCollectorDatabaseSession
- FailedJobGC                    -> GarbageCollectorFailedJob
- PasswordResetGC                -> GarbageCollectorPasswordReset
- GCRemcache                     -> GarbageCollectorRemcache
- StoryGC                        -> GarbageCollectorStory
- ImportUploadGarbageCollection  -> GarbageCollectorImportUpload
4 weeks ago
Your Name 57b3bf140b refactor: rename RemcacheGarbageCollector to GCRemcache 4 weeks ago
Your Name 3232761a74 fix: prevent remcache temp file leaks and add GC command
The remote avatar/media fetchers wrote temp files to storage/app/remcache/
and only unlinked them on the happy path. Any exception between the write
and the unlink (e.g. a cloud upload failure) leaked the file, and nothing
swept the directory.

- Wrap post-write logic in fetchAvatar() and remoteToCloud() in try/finally
  so the temp file is always removed, even on failure
- Add gc:remcache command to delete stale remcache files (default >24h old,
  preserves .gitignore, supports --hours and --dry-run)
- Schedule gc:remcache daily to clean up any stragglers

StoryFetch already handled cleanup via try/catch and was left unchanged.
4 weeks ago
Shlee 1f85fc8da2
Merge pull request #6954 from pixelfed/add-psalm-report-script
Add psalm report script
4 weeks ago
Your Name 878775cab9 chore: resolve psalm issues in admin commands and auth
- Add return type hints (void) and final class markers
- Guard null returns from newestBackup() and putFileAs() in BackupToCloud
- Type ask() default values as strings
- Fix uses_left fallback condition for null/zero max_uses
- Annotate AdminInvite::whereInviteCode and cast Str::uuid() to string
- Ignore local redis-data and mysql-9-data dev directories
4 weeks ago
Your Name fb69275cd7 chore: target PHP 8.4 in psalm config
Set phpVersion="8.4" so Psalm targets 8.4 explicitly instead of
inferring 8.3 from composer.json's ^8.3|^8.4 constraint.
4 weeks ago
Shlee 4b45ac72b8
Merge pull request #6953 from pixelfed/add-psalm-report-script
chore: add composer psalm:report script for a full local txt report
4 weeks ago
Your Name 6eea565bab chore: add composer psalm:report script for a full local txt report
Adds a psalm:report script that ignores the baseline and writes a full
human-readable report to psalm-report.txt, including informational issues,
so all outstanding items to fix are surfaced in one file.
4 weeks ago
Shlee bbc15a64e7
Merge pull request #6952 from pixelfed/revert-hashtags-collation
Revert hashtags collation migration from #6098
4 weeks ago
Your Name 4056747666 Revert hashtags collation migration from #6098
Migration failed with a duplicate entry error: recollating to
utf8mb4_unicode_520_ci causes previously-distinct hashtag names/slugs
to collide on the unique indexes. Reverting until the data is
de-duplicated first.
4 weeks ago
Shlee 0e77345930
Merge pull request #6951 from pixelfed/shleeable-patch-1
Shleeable patch 1
4 weeks ago
Shlee 765e10ea66
Update php-pint.yml 4 weeks ago
Shlee 338d4da427
Update php-laravel-tests.yml 4 weeks ago
Shlee 9dfb5c062e
Update php-larastan.yml 4 weeks ago
Shlee 336f5f899f
Merge pull request #6098 from bpeel/hashtags-outside-bmp
Fix hashtags usings scripts outside the BMP on MySQL
4 weeks ago
Shlee 27768cd69c
Create HashtagCollationTest.php 4 weeks ago