You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/decisions/0003-runtime-architecture.rst
+92-11Lines changed: 92 additions & 11 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -9,36 +9,57 @@ Status
9
9
Context
10
10
*******
11
11
12
-
The :doc:`0002-user-groups-model-foundations` introduced a unified model for user grouping based on configurable, pluggable criteria. The foundational model defines the data structure, scope constraints, and the decision to use registry-based criterion types that can be dynamically evaluated against user data.
12
+
The :doc:`0002-user-groups-model-foundations` introduced a unified model for user groups based on configurable, pluggable criteria. The foundational model defines the data structure, scope constraints, and the decision to use registry-based criterion types that can be dynamically evaluated against user data.
13
13
14
14
To make this foundation functional, we need a runtime architecture that enables dynamic evaluation, plugin discovery, and backend integration for data retrieval. This ADR defines how the pluggable criterion system works in practice, ensuring a flexible, scalable, and extensible runtime system that supports new criteria types, reusable data access patterns, and consistent evaluation performance.
15
15
16
16
The chosen approach prioritizes extensibility and operational efficiency through runtime registration while accepting increased runtime overhead as a necessary trade-off for long-term maintainability and plugin ecosystem support.
17
17
18
-
Key Concepts
19
-
============
18
+
Architectural Overview
19
+
======================
20
20
21
-
Visit :doc:`0002-user-groups-model-foundations` for the foundational model details.
21
+
The runtime architecture orchestrates four main components to transform static group definitions into dynamic user membership:
22
22
23
-
The runtime architecture builds upon the foundational model and introduces several key components:
23
+
**High-Level Flow:**
24
24
25
-
* **Criterion Type Class**: A pluggable Python class implementing evaluation and validation logic for a specific rule type defined in the user groups model. Each criterion type is registered in a centralized registry for runtime resolution.
26
-
* **Criteria Registry (Manager)**: A centralized runtime registry for resolving available criterion types by their string identifiers.
27
-
* **Evaluation Engine**: A core component responsible for computing a group's dynamic membership by orchestrating criterion evaluation.
28
-
* **Backend Clients**: Abstraction layer for data sources (e.g., MySQL via Django ORM, Superset API) that provide reusable data access methods.
Complete runtime flow showing the interaction between pluggable criteria, backend data retrieval, evaluation engine, and user group service. This example demonstrates creating a group for "students who have not logged in for more than 10 days AND have less than 40% course progress."
31
+
32
+
**Component Interaction:**
33
+
34
+
1. **Plugin Discovery**: The Criteria Registry loads and validates all available criterion types at startup, making them available for group configuration.
35
+
36
+
2. **Group Configuration**: When creating a group, the system validates that specified criterion types exist in the registry and are compatible with the group's scope.
37
+
38
+
3. **Dynamic Evaluation**: The Evaluation Engine orchestrates membership computation by:
39
+
40
+
* Loading criterion instances from the registry
41
+
* Using Backend Clients to access required data (users, enrollments, etc.)
42
+
* Combining individual criterion results using boolean logic
43
+
* Updating the membership storage
44
+
45
+
4. **Data Abstraction**: Backend Clients provide a unified interface to different data sources, allowing criteria to focus on business logic rather than data access details.
46
+
47
+
This architecture enables the system to scale from simple manual groups to complex dynamic segmentation while maintaining consistent interfaces and extensibility points.
29
48
30
49
Decision
31
50
********
32
51
33
52
I. Extensible Parts of the Model
34
53
=================================
35
54
55
+
This section establishes the foundation for extensibility by defining how new data sources and criterion types can be added to the system without modifying core. The key insight is separating data access concerns from business logic through backend abstraction.
56
+
36
57
Define extensible data sources and criteria types
37
58
-------------------------------------------------
38
59
39
60
To enable extensibility without modifying core platform code, we will support two main extension points:
40
61
41
-
* **Data Sources**: Developers will be able to connect new data sources by providing backend clients and registering them through a standard entry point. The system will provide reusable tools (e.g., query helpers) to make it easier to get the needed data.
62
+
* **Data Sources**: Developers will be able to connect new data sources by providing backend clients and registering them through configurations. The system will provide reusable tools (e.g., query helpers) to make it easier to get the needed data.
42
63
* **Criteria Types**: Developers will be able to define new ways of selecting users (e.g., "Visited unit X") along with the logic and fields needed to evaluate them, following the Registry-Based Criteria Subtypes approach from :doc:`ADR 0002 <0002-user-groups-model-foundations>`.
43
64
44
65
Adopt backend-managed data access with scope-aware abstraction
@@ -63,12 +84,14 @@ To support extensibility of data sources, we will:
63
84
64
85
* Allow registration of new backend clients through Django configuration settings, enabling developers to define their own backend clients that inherit from the base ``BackendClient`` class.
65
86
* Support configuration of multiple backends for different data sources, with each backend registered and discoverable through Django's configuration system.
66
-
* Enable the same base backend type to be configured differently for different deployment environments or data source variations.
87
+
* Enable the same base backend type to be configured differently for different deployment environments.
67
88
* Provide a registry mechanism that allows the evaluation engine to discover and select appropriate backends based on criterion type requirements.
68
89
69
90
II. Criteria Template Classes and Base Framework
70
91
================================================
71
92
93
+
This section defines how criterion type templates from :doc:`0002-user-groups-model-foundations` become functional criteria types. The focus is on creating a consistent interface that enables validation, configuration, and evaluation while maintaining flexibility for diverse criterion types.
94
+
72
95
Adopt runtime framework approach for criterion type templates
To implement the schema-light database design established in ADR 0002 while ensuring complete encapsulation of criterion behavior, we will:
123
+
124
+
* Delegate all criteria-specific logic to the criterion type class, making it responsible for:
125
+
126
+
* **Configuration validation**: Define accepted operators (e.g., >, !=, in) and expected configuration schema (e.g., integer days, list of strings)
127
+
* **Data access**: Handle retrieval of user data needed for evaluation
128
+
* **Evaluation logic**: Implement the core logic that determines which users match the criterion
129
+
* **Schema definition**: Expose machine-readable configuration requirements for UI generation
130
+
* **Error handling**: Provide clear error messages for invalid configurations
131
+
132
+
* Keep the model schema minimal and extensible by not enforcing structure or constraints on the config field at the database level.
133
+
* Execute validation when groups are created or updated, ensuring criterion configurations are validated before being saved to the database.
134
+
* Enable extension without schema migrations by shifting all enforcement to the type layer.
135
+
* Ensure consistent behavior across all criterion types by requiring each type class to implement the complete interface.
136
+
96
137
III. Runtime Registry System
97
138
============================
98
139
140
+
This section establishes how the system discovers and manages available criterion types at runtime. The registry serves as the central authority for criterion types, enabling dynamic loading, conflict detection, and plugin ecosystem support.
141
+
142
+
Implement registry-based criterion types with runtime resolution
@@ -139,6 +194,8 @@ To manage criterion type registration and detect conflicts systematically, we wi
139
194
IV. Evaluation Engine and Membership Computation
140
195
================================================
141
196
197
+
This section defines the core runtime component that transforms group criteria into actual user membership. The evaluation engine orchestrates the entire process from criterion loading to membership storage, supporting both simple AND logic and complex boolean expressions.
198
+
142
199
Introduce an evaluation engine to resolve dynamic group membership
To implement the unified group type approach established in ADR 0002, we will:
236
+
237
+
* Design all group types to use the same evaluation interface, whether they are manual or dynamic.
238
+
* Implement manual groups through a special criterion type that handles explicit user assignment.
239
+
* Enable consistent access patterns across all group types by using the same ``UserGroupMembership`` table and evaluation workflow.
240
+
* Ensure the evaluation engine can process any group type without requiring special handling based on the group's population method.
241
+
* Support the derived group type classification by determining type based on the configured criterion types.
242
+
164
243
V. Orchestration Layer and Integration
165
244
======================================
166
245
246
+
This section defines how all the runtime components work together through high-level orchestration functions. It establishes clean separation between business logic and data models while enabling dynamic UI generation and flexible group management workflows.
247
+
167
248
Use orchestrator functions for group operations management
0 commit comments