refactor: add durable transfer planning checkpoints

This commit is contained in:
jxxghp
2026-08-27 13:16:33 +08:00
parent 49d30e5fdf
commit 23bff6b2bb
41 changed files with 7401 additions and 1098 deletions
+5 -5
View File
@@ -1,12 +1,12 @@
{
"application": {
"covered_lines": 9341,
"percent": 77.85,
"statements": 11999
"covered_lines": 9572,
"percent": 78.06,
"statements": 12263
},
"domain": {
"covered_lines": 3390,
"percent": 79.24,
"covered_lines": 3392,
"percent": 79.29,
"statements": 4278
}
}
+7 -2
View File
@@ -1441,8 +1441,8 @@
"runtime_only": true
}
},
"edge_count": 6827,
"edge_sha256": "34e2be621e40f0f07ff04065655446c4ad0062883701f9e1e2235c29359900f7",
"edge_count": 6832,
"edge_sha256": "eb4b2f9b9689496a7821aeb151c64430cc8654b186aba50f2b7873ae09b71b39",
"edges": [
"app -> app.runtime",
"app -> app.runtime.compat",
@@ -4998,8 +4998,10 @@
"app.chain.transfer -> app.domain.context",
"app.chain.transfer -> app.domain.episode",
"app.chain.transfer -> app.domain.meta",
"app.chain.transfer -> app.domain.meta.metaanime",
"app.chain.transfer -> app.domain.meta.metabase",
"app.chain.transfer -> app.domain.meta.metamusic",
"app.chain.transfer -> app.domain.meta.metavideo",
"app.chain.transfer -> app.domain.metainfo",
"app.chain.transfer -> app.foundation",
"app.chain.transfer -> app.foundation.singleton",
@@ -5807,6 +5809,7 @@
"app.modules.filemanager.module -> app.application.directory",
"app.modules.filemanager.module -> app.application.messaging",
"app.modules.filemanager.module -> app.application.messaging.message",
"app.modules.filemanager.module -> app.application.transfer",
"app.modules.filemanager.module -> app.domain",
"app.modules.filemanager.module -> app.domain.context",
"app.modules.filemanager.module -> app.domain.meta",
@@ -5958,6 +5961,7 @@
"app.modules.filemanager.transhandler -> app.application.directory",
"app.modules.filemanager.transhandler -> app.application.messaging",
"app.modules.filemanager.transhandler -> app.application.messaging.message",
"app.modules.filemanager.transhandler -> app.application.transfer",
"app.modules.filemanager.transhandler -> app.domain",
"app.modules.filemanager.transhandler -> app.domain.context",
"app.modules.filemanager.transhandler -> app.domain.meta",
@@ -7903,6 +7907,7 @@
"app.startup.initializers.modules -> app.chain.site",
"app.startup.initializers.modules -> app.chain.subscribe",
"app.startup.initializers.modules -> app.chain.tmdb",
"app.startup.initializers.modules -> app.chain.transfer",
"app.startup.initializers.modules -> app.chain.workflow",
"app.startup.initializers.modules -> app.command",
"app.startup.initializers.modules -> app.db",
+11 -14
View File
@@ -1587,15 +1587,14 @@
"union-attr": 2
},
"app/chain/transfer.py": {
"arg-type": 65,
"assignment": 26,
"arg-type": 57,
"assignment": 25,
"attr-defined": 4,
"func-returns-value": 1,
"misc": 2,
"no-any-return": 3,
"no-redef": 2,
"no-untyped-call": 8,
"no-untyped-def": 15,
"no-untyped-def": 14,
"operator": 3,
"return-value": 2,
"truthy-function": 5,
@@ -2105,15 +2104,14 @@
"union-attr": 8
},
"app/modules/filemanager/module.py": {
"arg-type": 21,
"assignment": 9,
"arg-type": 19,
"assignment": 4,
"attr-defined": 1,
"empty-body": 1,
"no-any-return": 2,
"no-untyped-call": 6,
"no-untyped-call": 3,
"no-untyped-def": 6,
"truthy-function": 4,
"type-arg": 4,
"type-arg": 3,
"var-annotated": 3
},
"app/modules/filemanager/storages/__init__.py": {
@@ -2203,15 +2201,14 @@
"union-attr": 32
},
"app/modules/filemanager/transhandler.py": {
"arg-type": 19,
"assignment": 8,
"arg-type": 18,
"assignment": 2,
"attr-defined": 1,
"misc": 1,
"no-any-return": 1,
"no-redef": 1,
"no-untyped-call": 1,
"no-untyped-def": 4,
"operator": 7,
"no-untyped-def": 3,
"operator": 6,
"type-arg": 2,
"union-attr": 2
},
-25
View File
@@ -306,9 +306,6 @@
"app/application/agenttask.py": {
"I001": 1
},
"app/application/chain/context.py": {
"I001": 1
},
"app/application/chain/data.py": {
"I001": 1
},
@@ -414,9 +411,6 @@
"app/chain/media.py": {
"E731": 2
},
"app/chain/transfer.py": {
"E402": 21
},
"app/command.py": {
"I001": 1
},
@@ -676,13 +670,6 @@
"app/modules/filemanager/__init__.py": {
"I001": 1
},
"app/modules/filemanager/module.py": {
"I001": 1
},
"app/modules/filemanager/transhandler.py": {
"F541": 2,
"I001": 1
},
"app/modules/filter/__init__.py": {
"I001": 1
},
@@ -996,9 +983,6 @@
"app/runtime/extensions/managed_resource_adapter.py": {
"I001": 1
},
"app/runtime/extensions/module/dispatcher.py": {
"I001": 1
},
"app/runtime/extensions/module_manager.py": {
"I001": 1
},
@@ -1607,9 +1591,6 @@
"tests/test_music_torrents.py": {
"I001": 1
},
"tests/test_music_transfer.py": {
"I001": 1
},
"tests/test_music_workflows.py": {
"F401": 1
},
@@ -1855,9 +1836,6 @@
"tests/test_transfer_history_write_path.py": {
"I001": 1
},
"tests/test_transfer_job_manager.py": {
"I001": 1
},
"tests/test_transfer_mark_torrent_completed.py": {
"I001": 1
},
@@ -1867,9 +1845,6 @@
"tests/test_transfer_movie_collection.py": {
"I001": 1
},
"tests/test_transfer_preview.py": {
"I001": 1
},
"tests/test_transfer_queue_count.py": {
"I001": 1
},
+83 -49
View File
@@ -1518,8 +1518,7 @@
"ChainEventType.StorageOperSelection": {
"consumer_fingerprints": [],
"producer_fingerprints": [
"e5cfe4cabe945282695a3490147ee73acb3c6f8a4889fe510e8c0d3d2044e476",
"e5cfe4cabe945282695a3490147ee73acb3c6f8a4889fe510e8c0d3d2044e476"
"76a388b1caf87a51cacf9d7534f64576f7c98e0af6b604d30114dab893066d96"
]
},
"ChainEventType.SubscribeCompletionCheck": {
@@ -1538,14 +1537,13 @@
"ChainEventType.TransferIntercept": {
"consumer_fingerprints": [],
"producer_fingerprints": [
"144f9ffac815b2f58ade53881df0ce43381a7b1adff62f53a019794b801a0cd7",
"d7ee7c450874ea4bf6ea97c903b9cd3ebeab7266834c22e1a699d067205e8912"
"410f9308657c3c228e5357acf2e9a083c4fe6476c3b4ddaf240cab385d8bd4af"
]
},
"ChainEventType.TransferOverwriteCheck": {
"consumer_fingerprints": [],
"producer_fingerprints": [
"e761a75952ab6835e67b2c43c671f6361f1977690cfd7724f79439229408af40"
"be3334d20e9aa1fd641fe67f0bc3abd3ef48433728ddb76538cfbb475b4dc92b"
]
},
"ChainEventType.TransferRename": {
@@ -1809,11 +1807,11 @@
]
}
},
"fact_count": 116,
"fact_count": 114,
"invalid_consumer_count": 0,
"invalid_producer_count": 0,
"producer_call_count": 99,
"producer_event_reference_count": 100,
"producer_call_count": 97,
"producer_event_reference_count": 98,
"producers": [
{
"caller": "app.agent.orchestrator",
@@ -2495,22 +2493,10 @@
"events": [
"ChainEventType.StorageOperSelection"
],
"fingerprint": "e5cfe4cabe945282695a3490147ee73acb3c6f8a4889fe510e8c0d3d2044e476",
"fingerprint": "76a388b1caf87a51cacf9d7534f64576f7c98e0af6b604d30114dab893066d96",
"invalid": false,
"method": "send_event",
"qualname": "TransferChain.__handle_transfer",
"receiver_kind": "injected_event_manager"
},
{
"caller": "app.chain.transfer",
"dynamic": false,
"events": [
"ChainEventType.StorageOperSelection"
],
"fingerprint": "e5cfe4cabe945282695a3490147ee73acb3c6f8a4889fe510e8c0d3d2044e476",
"invalid": false,
"method": "send_event",
"qualname": "TransferChain.__handle_transfer",
"qualname": "TransferChain.__select_storage_oper",
"receiver_kind": "injected_event_manager"
},
{
@@ -2673,22 +2659,22 @@
"events": [
"ChainEventType.TransferIntercept"
],
"fingerprint": "d7ee7c450874ea4bf6ea97c903b9cd3ebeab7266834c22e1a699d067205e8912",
"fingerprint": "410f9308657c3c228e5357acf2e9a083c4fe6476c3b4ddaf240cab385d8bd4af",
"invalid": false,
"method": "send_event",
"qualname": "TransHandler.__transfer_dir",
"qualname": "TransHandler.__intercept_transfer",
"receiver_kind": "canonical_singleton"
},
{
"caller": "app.modules.filemanager.transhandler",
"dynamic": false,
"events": [
"ChainEventType.TransferIntercept"
"ChainEventType.TransferOverwriteCheck"
],
"fingerprint": "144f9ffac815b2f58ade53881df0ce43381a7b1adff62f53a019794b801a0cd7",
"fingerprint": "be3334d20e9aa1fd641fe67f0bc3abd3ef48433728ddb76538cfbb475b4dc92b",
"invalid": false,
"method": "send_event",
"qualname": "TransHandler.__transfer_file",
"qualname": "TransHandler.__resolve_overwrite",
"receiver_kind": "canonical_singleton"
},
{
@@ -2715,18 +2701,6 @@
"qualname": "TransHandler.get_rename_path",
"receiver_kind": "canonical_singleton"
},
{
"caller": "app.modules.filemanager.transhandler",
"dynamic": false,
"events": [
"ChainEventType.TransferOverwriteCheck"
],
"fingerprint": "e761a75952ab6835e67b2c43c671f6361f1977690cfd7724f79439229408af40",
"invalid": false,
"method": "send_event",
"qualname": "TransHandler.transfer_media",
"receiver_kind": "canonical_singleton"
},
{
"caller": "app.modules.navidrome",
"dynamic": false,
@@ -3005,7 +2979,7 @@
}
],
"static_consumer_count": 16,
"static_producer_call_count": 98
"static_producer_call_count": 96
},
"event_specs": {
"ChainEventType.AgentLLMProvider": {
@@ -5825,6 +5799,28 @@
"timeout_policy": "caller_budget",
"version": 1
},
"execute_transfer_plan": {
"aggregation": "first_non_empty",
"error_policy": "isolate_provider",
"execution": "sync_or_async",
"family": "storage",
"input_contract": "TransferPlanCheckpoint",
"plugin_short_circuit": true,
"public_to_plugins": false,
"required_parameters": [
"checkpoint",
"mediainfo",
"meta",
"source_oper",
"target_oper"
],
"result_contract": "TransferInfo | None",
"result_shape": "any",
"supports_async": true,
"supports_sync": true,
"timeout_policy": "caller_budget",
"version": 1
},
"filter_torrents": {
"aggregation": "ordered_list_merge",
"error_policy": "isolate_provider",
@@ -6864,6 +6860,37 @@
"timeout_policy": "caller_budget",
"version": 1
},
"plan_transfer": {
"aggregation": "first_non_empty",
"error_policy": "isolate_provider",
"execution": "sync_or_async",
"family": "storage",
"input_contract": "TransferPlanningInput",
"plugin_short_circuit": true,
"public_to_plugins": false,
"required_parameters": [
"episodes_info",
"fileitem",
"library_category_folder",
"library_type_folder",
"mediainfo",
"meta",
"planning_input",
"preview",
"scrape",
"source_oper",
"target_directory",
"target_path",
"target_storage",
"transfer_type"
],
"result_contract": "TransferPlanCheckpoint | None",
"result_shape": "any",
"supports_async": true,
"supports_sync": true,
"timeout_policy": "caller_budget",
"version": 1
},
"recognize_media": {
"aggregation": "first_non_empty",
"error_policy": "isolate_provider",
@@ -7947,10 +7974,10 @@
}
},
"run_module": {
"call_count": 264,
"call_count": 265,
"dynamic_call_count": 0,
"dynamic_calls": [],
"method_count": 214,
"method_count": 215,
"methods": {
"anilist_credits": [
{
@@ -8769,6 +8796,13 @@
"mode": "sync"
}
],
"execute_transfer_plan": [
{
"caller": "app.chain",
"count": 1,
"mode": "sync"
}
],
"filter_torrents": [
{
"caller": "app.chain",
@@ -9190,6 +9224,13 @@
"mode": "sync"
}
],
"plan_transfer": [
{
"caller": "app.chain",
"count": 1,
"mode": "sync"
}
],
"recognize_media": [
{
"caller": "app.chain._recognition",
@@ -9514,13 +9555,6 @@
"mode": "sync"
}
],
"transfer": [
{
"caller": "app.chain",
"count": 1,
"mode": "sync"
}
],
"transfer_completed": [
{
"caller": "app.chain",