Phase 14e-2: domain-event listeners (file cleanup + cache invalidation)#32
Merged
Conversation
Scriptor-side companion to 14e-1 (iManager PSR-14 dispatcher +
storage emits). Container now wires a sync dispatcher on top of the
in-memory subscriber provider, hands it to SqliteStorage, and
subscribes two listeners:
Scriptor\Boot\Events\ItemFileCleanupListener
- Subscribes to ItemDeleted.
- Walks FileRepository::findByItem() while the row is still
reachable (Plan §14e contract: dispatcher fires before the SQL
DELETE so the FK cascade hasn't dropped the metadata yet) and
asks FileStorage to drop each asset.
- Also scrubs every <W>x<H>_<file> thumbnail under <dir>/thumbnail/
via FileStorage::absolutePath() + scandir, matching the upload
convention (suffix `_<name>` plus a `\d+x\d+_` prefix). Tolerates
missing dirs and unreadable siblings.
Scriptor\Boot\Events\PageCacheInvalidationListener
- Subscribes to ItemCreated, ItemUpdated, ItemDeleted.
- Filters by category id (Pages only — Users mutations don't
invalidate the rendered-HTML cache).
- Calls Cache::clear() on the FilesystemCache. BasicTheme keys
cache entries by md5(host + REQUEST_URI), which we can't recreate
at event-time, so this is a global flush of the section cache
until the cache learns tags / per-page prefixes.
ImanagerBootstrap:
- Registers SubscriberListenerProvider (typed bind) +
ListenerProviderInterface (alias) + EventDispatcherInterface
(SyncEventDispatcher composing the provider).
- SqliteStorage is now built with the dispatcher.
- wireDomainEventListeners() subscribes both listeners through the
provider; listener instances are constructed lazily on first
fire, and the cache-invalidator caches its watched-category id
after the first lookup so it doesn't re-resolve on every event.
composer.lock: pulls in psr/event-dispatcher 1.0.0 (transitively
through bigins/imanager 14e-1).
Manual smoke (PHP built-in server, fresh PNG fixture):
POST /editor/pages/edit/ → 302; new item id=11 created
POST /editor/api/upload → 200; fileId=5, asset + 300x300
thumbnail on disk
Frontend hit → 1 cache file
GET /editor/pages/delete/?… → 302
Verifications after delete:
items row gone (0)
files row gone (0; FK cascade)
asset 14e2.png gone (ItemFileCleanupListener)
thumbnail/300x300_14e2.png gone (ItemFileCleanupListener)
cache files 0 (PageCacheInvalidationListener)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Scriptor-side companion to 14e-1 (iManager PSR-14 dispatcher + storage
emits). The container now wires a sync dispatcher on top of the
in-memory subscriber provider, hands it to
SqliteStorage, andsubscribes two listeners.
Scriptor\Boot\Events\ItemFileCleanupListener(subscribes toItemDeleted):FileRepository::findByItem()while the row is stillreachable (Plan §14e contract: dispatcher fires before the SQL
DELETE so the FK cascade hasn't dropped the metadata yet) and asks
FileStorageto drop each asset.<W>x<H>_<file>thumbnail under<dir>/thumbnail/via
scandir, matching the upload convention. Tolerates missingdirs and unreadable siblings.
Scriptor\Boot\Events\PageCacheInvalidationListener(subscribesto
ItemCreated/ItemUpdated/ItemDeleted):invalidate the rendered-HTML cache).
CacheInterface::clear(). BasicTheme keys cache entries bymd5(host + REQUEST_URI), which we can't recreate at event-time,so this is a global flush until the cache learns tags / per-page
prefixes.
prefixes.
ImanagerBootstrap:SubscriberListenerProvider+ alias toListenerProviderInterface+EventDispatcherInterface(
SyncEventDispatchercomposing the provider).SqliteStorageis now built with the dispatcher.wireDomainEventListeners()subscribes both listeners through theprovider; listener instances are constructed lazily on first fire,
and the cache-invalidator caches its watched-category id after the
first lookup.
composer.lock: pulls inpsr/event-dispatcher 1.0.0(transitivelythrough
bigins/imanagerat 14e-1).Test plan
fileId, asset + 300×300 thumb on disk14e2.pnggone (ItemFileCleanupListener)thumbnail/300x300_14e2.pnggone (ItemFileCleanupListener)