feat: thumbnail generator plugin with configurable size/format

- ThumbnailGeneratorPort in domain (bytes + config → resized bytes)
- adapters-thumbnail: ImageThumbnailGenerator using image crate
- ThumbnailGeneratorPlugin reads width/height/format/profile from step config
- PostgresDerivativeRepository + 012_derivatives migration
- Seeded in extract_metadata pipeline as step 2 (300x300 webp)
- Standalone generate_derivative pipeline for on-demand use
This commit is contained in:
2026-05-31 20:44:55 +02:00
parent 45669ec848
commit 35d5baf7be
15 changed files with 1155 additions and 18 deletions

View File

@@ -1,17 +1,28 @@
-- Default plugins matching worker's InMemoryPluginRegistry
INSERT INTO plugins (plugin_id, name, plugin_type, is_enabled, configuration)
VALUES
('a0000000-0000-4000-8000-000000000001', 'metadata_extractor', 'media_processor', true, '{}'),
('a0000000-0000-4000-8000-000000000002', 'sidecar_sync', 'sidecar_writer', true, '{}'),
('a0000000-0000-4000-8000-000000000003', 'no_op', 'scheduled_task', true, '{}')
('a0000000-0000-4000-8000-000000000001', 'metadata_extractor', 'media_processor', true, '{}'),
('a0000000-0000-4000-8000-000000000002', 'sidecar_sync', 'sidecar_writer', true, '{}'),
('a0000000-0000-4000-8000-000000000003', 'no_op', 'scheduled_task', true, '{}'),
('a0000000-0000-4000-8000-000000000004', 'thumbnail_generator', 'media_processor', true, '{}')
ON CONFLICT (plugin_id) DO NOTHING;
-- Pipeline: extract_metadata → metadata_extractor
-- Pipeline: extract_metadata → metadata_extractor, then thumbnail_generator
INSERT INTO processing_pipelines (pipeline_id, trigger_event, steps)
VALUES (
'b0000000-0000-4000-8000-000000000001',
'extract_metadata',
'[{"plugin_id": "a0000000-0000-4000-8000-000000000001", "step_order": 0, "configuration": {}}]'
'[{"plugin_id": "a0000000-0000-4000-8000-000000000001", "step_order": 0, "configuration": {}},
{"plugin_id": "a0000000-0000-4000-8000-000000000004", "step_order": 1, "configuration": {"width": "300", "height": "300", "format": "webp", "profile": "ThumbnailSquare"}}]'
)
ON CONFLICT (pipeline_id) DO NOTHING;
-- Pipeline: generate_derivative (standalone, configurable per-step)
INSERT INTO processing_pipelines (pipeline_id, trigger_event, steps)
VALUES (
'b0000000-0000-4000-8000-000000000003',
'generate_derivative',
'[{"plugin_id": "a0000000-0000-4000-8000-000000000004", "step_order": 0, "configuration": {"width": "300", "height": "300", "format": "webp", "profile": "ThumbnailSquare"}}]'
)
ON CONFLICT (pipeline_id) DO NOTHING;