-
-
Notifications
You must be signed in to change notification settings - Fork 24
Description
Target branch: release-0.9.x
Current behavior
The current deserialization behavior recurses into 'children' models when it encounters a model with a self-referential foreign key (FK). This contributes to its monolithic nature and its memory consumption by requiring the algorithm to track more data in memory to ensure comprehensive deserialization of store data.
The serialization process tracks the FK value for self-referential models in a field called _self_ref_fk. This allows it to lookup those FK records using that value.
Additionally, the Morango registry, which tracks the syncable models defined by any apps using Morango, orders them according to their cross-model FK dependencies.
Desired behavior
The deserialization algorithm would be more amenable to the streaming architecture by ordering the store records more intelligently before they enter the pipeline. Combined with the existing ordering by the Morango registry of syncable models, this should create a predictable order in which store records can be properly deserialized without broken FKs.
Enhancements
Data Model
This specifically addresses self-referential FK ordering within the same model (e.g., parent-child relationships in hierarchical data). The registry handles cross-model dependencies, but self-referential FKs need special ordering.
- A new nullable field
_self_ref_ordershould be added to theAbstractStorewith type ofInteger - The new field be greater than or equal to
0unless null - Django model migrations should be created to add the new field to
StoreandBuffer - The
SyncableModelshould have a new tuple attributemorango_orderingwhich should hold one or more field expressions in the format that Django uses fororder_by()(similar toMeta.ordering) - The
SyncableModelRegistry.get_model_querysetsshould order its querysets according tomorango_orderingif set; nulls should always be last
Serialization
Update StoreUpdate transform in serialize.py to set _self_ref_order during Store record creation and updates.
- The
_handle_store_createmethod should be updated:- if the model is not self-referential, the order field should be null
- if
_self_ref_fkisNoneand the model is self-referential, the order field should be0 - otherwise, it should query for the parent's order (the
Store._self_ref_orderforid=_self_ref_fk)
- The
_handle_store_createmethod should be updated:- to detect if the
_self_ref_fkhas changed, and if so, update the order like_handle_store_create
- to detect if the
Compatibility
Morango should communicate during a sync whether it supports ordering with _self_ref_order. Later on, this will allow Morango to determine whether it can fully streamline the sync.
- A new capability
SELF_REF_ORDERshould exist inconstants/capabilities.py - The capability should be provided by default during a sync
- If the client device sends the capability, the server should trust and expect
_self_ref_orderin the sent data - If the client does not send the capability, the server should compute the order during the
dequeuestage
Transmission
Value add
Provides more certainty to the pipeline that we process store records in the order of their relational dependency in the DB.
Possible tradeoffs
- Morango defines other fields on
SyncableModelfor consumers to override, which could be better to have in the modelMeta. For example, you can defineorderingin the modelMeta, but we're puttingmorango_orderingon the model itself. - Morango could let the app models provide the ordering information through a defined API, but backwards compatibility would still need logic to determine it manually. Therefore always leveraging that logic seems sensible, unless we let go of backwards compatibility
- We're adding yet another capability. While it isn't a concern at the moment, growth of the capabilities should be monitored since it's sent in an HTTP header, which has inconsistent limits on size depending on server.
AI usage
AI was used for brainstorming approaches.