synology_apm_repo.sdk.units.dispatch module¶
Provider dispatch. Lives in units, not catalog, so catalog never
has to import units and form a cycle. target_type in {VM,PC,PS} ->
DeviceProvider; FS -> FsProvider; SaaS ({M365,GW}) routes through
saas_provider_for, which picks an application-layer provider by the
owning Workload’s catalog-derived sub_type and degrades to
RawObjectProvider on recognition failure.
- synology_apm_repo.sdk.units.dispatch.SUPPORTED_TARGET_TYPES = frozenset({TargetType.FS, TargetType.PC, TargetType.PS, TargetType.VM})¶
target_typevaluesprovider_foralone can build a provider for — VM/PC/PS/FS only. SaaS dispatch needs the owningWorkload(forsub_type), so it lives in the separatesaas_provider_forbelow; seeSUPPORTED_SAAS_SUB_TYPESfor that axis’s equivalent. Membership here doesn’t guarantee every individual version resolves — a specific PC/PS version can still have every disk fragment unresolvable at runtime (device_pcps.PcpsDiskTree’s own diagnostic-node path).
- synology_apm_repo.sdk.units.dispatch.SUPPORTED_SAAS_SUB_TYPES = frozenset({'CALENDAR', 'CONTACT', 'DRIVE', 'GROUP_EXCHANGE', 'MAIL', 'SITE', 'TEAMS', 'TEAM_DRIVE', 'USER_CHAT', 'USER_DRIVE', 'USER_EXCHANGE'})¶
Workload.sub_typevaluessaas_provider_forcan attempt an application-layer provider for. This does not guarantee every individual version of a workload with a recognized sub_type succeeds (a specific version can still degrade to raw at runtime) — same caveatSUPPORTED_TARGET_TYPESalready carries for PC/PS.
- synology_apm_repo.sdk.units.dispatch.is_supported(workload)¶
Whether
workloadhas a chance at an application-layer provider (VM/PC/PS/FS viaprovider_for, or a recognized SaaSsub_typeviasaas_provider_for) — a plain, no-I/O check overSUPPORTED_TARGET_TYPES/SUPPORTED_SAAS_SUB_TYPES, for callers (e.g. the CLI’sdoctorcommand, viaRepository.workload_is_supported) that want to report “not yet supported” without constructing a provider. Carries the same caveat those two constants do:Truedoesn’t guarantee every individual version actually resolves — a specific version can still fail construction or degrade to a raw fallback at runtime.
- async synology_apm_repo.sdk.units.dispatch.provider_for(repo, version)¶
Return the right
ClosableUnitProviderforversion, based on itstarget_typealone (VM/PC/PS/FS only).Async to match
UnitProvider’s own construction uniformity, not because this dispatch itself does I/O: thetarget_typebranch is a pure string comparison, and bothDeviceProvider.createandFsProvider.__init__construct with no I/O.- Raises:
UnsupportedDataFormatError –
version.target_typeis a SaaS type (M365/GW) — those need the owningWorkloadtoo (forsub_type); callsaas_provider_forinstead.
- async synology_apm_repo.sdk.units.dispatch.saas_provider_for(repo, workload, version, saas_streams, *, object_db_id=None)¶
Route one SaaS
Versionto its application-layer provider(s), by the owningWorkload.sub_type. Tries every candidate in_SAAS_SUB_TYPE_CANDIDATESrather than stopping at the first match — M365’sUSER_EXCHANGE/GROUP_EXCHANGEcan genuinely have Mail, Contact, and Calendar all present in the same version at once. Zero matches degrades toRawObjectProvider; exactly one is returned directly; more than one is wrapped inCompositeSaasProviderso every match stays reachable as a sibling top-level group.M365’s
USER_EXCHANGE/GROUP_EXCHANGEbundle Mail/Contact/ Calendar under one sub_type; GWS’s own account instead has independent workloads per app type ("MAIL"/"CONTACT"/"CALENDAR"), so its candidate lists carry only one entry each.saas_streams— the caller’s sharedSaasStreamCache(built against this samerepo, never one built independently — seeapi.repository._OpenCatalog) — is threaded into every candidate and the fallback alike, so a stream this call opens is reused by every other version of the same stream a later call resolves too, not just this call’s own sibling candidates.object_db_idonly reaches the fallbackRawObjectProviderconstruction — the application-layer candidates above resolve their own service DB internally.Async because each candidate
factory(...)genuinely reads (openssaas_obj, resolves its object-name index) to decide whether it recognizes this version at all — except when more than one candidate is offered for thissub_type(USER_EXCHANGE/GROUP_EXCHANGEtoday, per_SAAS_SUB_TYPE_CANDIDATES), in which case that read happens exactly once, up front, viaresolve_shared_saas_context, and every candidate reuses the result instead of each re-resolving the same(repo, version)’ssaas_obj/object-name index for itself. A single-candidatesub_typegetsshared=Nonehere, since there’s only one candidate to share the read with.
- async synology_apm_repo.sdk.units.dispatch.raw_fallback_provider_for(repo, version, saas_streams, *, object_db_id=None)¶
The degradation axis, made directly reachable: diagnostic tooling, the TUI’s
d-mode override, orsaas_provider_foritself (when no application-layer provider recognizes a version) can get a SaaS version’s raw object-name-index tree directly. Kept separate fromprovider_for’s dispatch — that one stays a hard refusal for a bareVersionwith noWorkload, keeping the diagnostic-only distinction visible at the type level.Async because
RawObjectProvider.createis — it opens the version’ssaas_obj(viasaas_streams) and resolves its object-name index.