synology_apm_repo.sdk.units.saas.tree_strategy.recursive_group_flat module¶
RecursiveGroupFlatTree: M365 Mail’s real folder hierarchy —
groups (folders) recurse via parent-pointer, like RecursiveTree, but
each group’s leaves (messages) live in a separate, flat, non-recursive
table instead of recursing themselves, combining the two schema shapes
every service-level DB in this project expands into (parent-pointer
recursion; a flat list optionally grouped by one key).
- class synology_apm_repo.sdk.units.saas.tree_strategy.recursive_group_flat.RecursiveGroupFlatTree(provider, *, group_table, group_columns, group_id_column, group_name_column, group_parent_column, group_root_id, leaf_table, leaf_columns, leaf_id_column, leaf_group_column, display_name, order_by, descending=False)¶
Bases:
objectM365 Mail’s real folder hierarchy:
mail_folder_tableis a real, named, self-referencing table (folder_id/folder_name/parent_folder_id, rooted at a synthetic anchor id exactly likeRecursiveTree’s ownroot_idconvention) whose rows are always folders — unlikeRecursiveTree/NamedGroupRecursiveTree’s own mixed tables, nois_folder()check is needed. Its leaves live in a separate, flat, non-recursive table keyed by its own group-fk column — a message never nests and never has children of its own. “Group” here means what it means forNamedGroupFlatTree/NamedGroupRecursiveTree(a real definitions table with its own display-name column), just recursive rather than flat, and with one id-space serving as both this table’s own recursion key and the leaf table’s own foreign key.Every key is a growing-prefix chain, one real folder id per level (e.g.
("inbox",),("inbox", "haha")), not a bare id the wayRecursiveTreekeys Drive: Mail stays a plainSaasWorkloadProvider(notRecursiveTreeSaasProvider), sounits/resolve.py’s generic ref-descent needs every non-leaf child’s key to be a genuine prefix of any deeper target’s key. A leaf’s key extends its own containing folder’s key by one more segment (its own leaf id).children_of()for one folder lists its real subfolders — always, even with zero backed-up messages, the entire point of this class — before that folder’s own leaves. Seechildren_of()itself for how each half is fetched and windowed.A genuine leaf’s own key naturally returns
[]fromchildren_of()with no explicit key-shape guard (unlike every sibling class in this package): a leaf’s own id never appears as any row’sparent_folder_idin either table. ANULLleaf_group_columnvalue is a documented non-concern the same way: it never matchesWHERE ... = ?, and real M365 rows always populate it.contact_folder_tablehas this exact same shape and could reuse this class later — out of scope for now,contact.pyis untouched.- async children_of(key, *, offset=0, limit=None)¶
One folder’s real subfolders (always, even with zero backed-up messages) before that folder’s own leaves. A folder’s own subfolder count is small (this mailbox’s own folder fan-out, never its message count), so
_list_subfoldersfully materializes and paginates it in Python, the same small-bounded-scan precedent_NamedGroupTable.list_top_levelalready establishes; only the leaf half issues a realWHERE/ORDER BY/LIMIT/OFFSETquery, windowed to cover only whatever part of[offset, offset+limit)the subfolders didn’t already satisfy.
- row_for(key)¶