flagsmith-common 3.10.1__tar.gz → 3.12.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/PKG-INFO +33 -3
- {flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/README.md +30 -2
- {flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/pyproject.toml +4 -2
- flagsmith_common-3.12.0/src/common/core/cli/run.py +79 -0
- {flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/common/core/constants.py +4 -0
- {flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/common/core/main.py +26 -4
- {flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/common/core/otel.py +50 -10
- flagsmith_common-3.12.0/src/common/core/types.py +3 -0
- flagsmith_common-3.12.0/src/task_processor/constants.py +4 -0
- {flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/task_processor/utils.py +31 -4
- {flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/LICENSE +0 -0
- {flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/common/__init__.py +0 -0
- {flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/common/core/__init__.py +0 -0
- {flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/common/core/app.py +0 -0
- {flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/common/core/cli/__init__.py +0 -0
- {flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/common/core/cli/healthcheck.py +0 -0
- {flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/common/core/docgen/__init__.py +0 -0
- {flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/common/core/docgen/events.py +0 -0
- {flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/common/core/logging.py +0 -0
- {flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/common/core/management/__init__.py +0 -0
- {flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/common/core/management/commands/__init__.py +0 -0
- {flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/common/core/management/commands/docgen.py +0 -0
- {flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/common/core/management/commands/start.py +0 -0
- {flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/common/core/management/commands/waitfordb.py +0 -0
- {flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/common/core/metrics.py +0 -0
- {flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/common/core/middleware.py +0 -0
- {flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/common/core/sentry.py +0 -0
- {flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/common/core/templates/docgen-events.md +0 -0
- {flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/common/core/templates/docgen-metrics.md +0 -0
- {flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/common/core/urls.py +0 -0
- {flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/common/core/utils.py +0 -0
- {flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/common/core/views.py +0 -0
- {flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/common/environments/permissions.py +0 -0
- {flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/common/features/__init__.py +0 -0
- {flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/common/features/multivariate/__init__.py +0 -0
- {flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/common/features/multivariate/serializers.py +0 -0
- {flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/common/features/serializers.py +0 -0
- {flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/common/features/versioning/__init__.py +0 -0
- {flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/common/features/versioning/serializers.py +0 -0
- {flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/common/gunicorn/__init__.py +0 -0
- {flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/common/gunicorn/conf.py +0 -0
- {flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/common/gunicorn/constants.py +0 -0
- {flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/common/gunicorn/logging.py +0 -0
- {flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/common/gunicorn/metrics.py +0 -0
- {flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/common/gunicorn/metrics_server.py +0 -0
- {flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/common/gunicorn/middleware.py +0 -0
- {flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/common/gunicorn/processors.py +0 -0
- {flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/common/gunicorn/utils.py +0 -0
- {flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/common/lint_tests.py +0 -0
- {flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/common/migrations/__init__.py +0 -0
- {flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/common/migrations/helpers/__init__.py +0 -0
- {flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/common/migrations/helpers/postgres_helpers.py +0 -0
- {flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/common/organisations/permissions.py +0 -0
- {flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/common/projects/permissions.py +0 -0
- {flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/common/prometheus/__init__.py +0 -0
- {flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/common/prometheus/utils.py +0 -0
- {flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/common/py.typed +0 -0
- {flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/common/test_tools/__init__.py +0 -0
- {flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/common/test_tools/plugin.py +0 -0
- {flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/common/test_tools/types.py +0 -0
- {flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/common/test_tools/utils.py +0 -0
- {flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/common/types.py +0 -0
- {flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/flagsmith_schemas/__init__.py +0 -0
- {flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/flagsmith_schemas/api.py +0 -0
- {flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/flagsmith_schemas/constants.py +0 -0
- {flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/flagsmith_schemas/dynamodb.py +0 -0
- {flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/flagsmith_schemas/py.typed +0 -0
- {flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/flagsmith_schemas/pydantic_types.py +0 -0
- {flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/flagsmith_schemas/types.py +0 -0
- {flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/flagsmith_schemas/utils.py +0 -0
- {flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/flagsmith_schemas/validators.py +0 -0
- {flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/task_processor/__init__.py +0 -0
- {flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/task_processor/admin.py +0 -0
- {flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/task_processor/apps.py +0 -0
- {flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/task_processor/decorators.py +0 -0
- {flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/task_processor/exceptions.py +0 -0
- {flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/task_processor/health.py +0 -0
- {flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/task_processor/managers.py +0 -0
- {flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/task_processor/metrics.py +0 -0
- {flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/task_processor/migrations/0001_initial.py +0 -0
- {flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/task_processor/migrations/0002_healthcheckmodel.py +0 -0
- {flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/task_processor/migrations/0003_add_completed_to_task.py +0 -0
- {flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/task_processor/migrations/0004_recreate_task_indexes.py +0 -0
- {flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/task_processor/migrations/0005_update_conditional_index_conditions.py +0 -0
- {flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/task_processor/migrations/0006_auto_20230221_0802.py +0 -0
- {flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/task_processor/migrations/0007_add_is_locked.py +0 -0
- {flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/task_processor/migrations/0008_add_get_task_to_process_function.py +0 -0
- {flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/task_processor/migrations/0009_add_recurring_task_run_first_run_at.py +0 -0
- {flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/task_processor/migrations/0010_task_priority.py +0 -0
- {flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/task_processor/migrations/0011_add_priority_to_get_tasks_to_process.py +0 -0
- {flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/task_processor/migrations/0012_add_locked_at_and_timeout.py +0 -0
- {flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/task_processor/migrations/0013_add_last_picked_at.py +0 -0
- {flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/task_processor/migrations/0014_add_trace_context.py +0 -0
- {flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/task_processor/migrations/0015_add_is_disabled.py +0 -0
- {flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/task_processor/migrations/__init__.py +0 -0
- {flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/task_processor/migrations/sql/0008_get_recurring_tasks_to_process.sql +0 -0
- {flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/task_processor/migrations/sql/0008_get_tasks_to_process.sql +0 -0
- {flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/task_processor/migrations/sql/0011_get_tasks_to_process.sql +0 -0
- {flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/task_processor/migrations/sql/0012_get_recurringtasks_to_process.sql +0 -0
- {flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/task_processor/migrations/sql/0013_get_recurringtasks_to_process.sql +0 -0
- {flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/task_processor/migrations/sql/0015_get_recurringtasks_to_process.sql +0 -0
- {flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/task_processor/migrations/sql/__init__.py +0 -0
- {flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/task_processor/models.py +0 -0
- {flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/task_processor/monitoring.py +0 -0
- {flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/task_processor/processor.py +0 -0
- {flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/task_processor/py.typed +0 -0
- {flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/task_processor/routers.py +0 -0
- {flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/task_processor/serializers.py +0 -0
- {flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/task_processor/task_registry.py +0 -0
- {flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/task_processor/task_run_method.py +0 -0
- {flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/task_processor/tasks.py +0 -0
- {flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/task_processor/threads.py +0 -0
- {flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/task_processor/types.py +0 -0
- {flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/task_processor/urls.py +0 -0
- {flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/task_processor/views.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: flagsmith-common
|
|
3
|
-
Version: 3.
|
|
3
|
+
Version: 3.12.0
|
|
4
4
|
Summary: Flagsmith's common library
|
|
5
5
|
Author: Matthew Elwell, Gagan Trivedi, Kim Gustyr, Zach Aysan, Francesco Lo Franco, Rodrigo López Dato, Evandro Myller, Wadii Zaim
|
|
6
6
|
License-Expression: BSD-3-Clause
|
|
@@ -32,6 +32,7 @@ Requires-Dist: flagsmith-flag-engine>6 ; extra == 'flagsmith-schemas'
|
|
|
32
32
|
Requires-Dist: inflection ; extra == 'otel'
|
|
33
33
|
Requires-Dist: opentelemetry-api>=1.25,<2 ; extra == 'otel'
|
|
34
34
|
Requires-Dist: opentelemetry-sdk>=1.25,<2 ; extra == 'otel'
|
|
35
|
+
Requires-Dist: opentelemetry-exporter-otlp-proto-grpc>=1.25,<2 ; extra == 'otel'
|
|
35
36
|
Requires-Dist: opentelemetry-exporter-otlp-proto-http>=1.25,<2 ; extra == 'otel'
|
|
36
37
|
Requires-Dist: sentry-sdk>=2.0.0,<3.0.0 ; extra == 'otel'
|
|
37
38
|
Requires-Dist: structlog>=24.4,<26 ; extra == 'otel'
|
|
@@ -39,6 +40,7 @@ Requires-Dist: typing-extensions ; extra == 'otel'
|
|
|
39
40
|
Requires-Dist: backoff>=2.2.1,<3.0.0 ; extra == 'task-processor'
|
|
40
41
|
Requires-Dist: django>4,<6 ; extra == 'task-processor'
|
|
41
42
|
Requires-Dist: django-health-check ; extra == 'task-processor'
|
|
43
|
+
Requires-Dist: environs<16 ; extra == 'task-processor'
|
|
42
44
|
Requires-Dist: opentelemetry-api>=1.25,<2 ; extra == 'task-processor'
|
|
43
45
|
Requires-Dist: prometheus-client>=0.0.16 ; extra == 'task-processor'
|
|
44
46
|
Requires-Dist: pyfakefs>=6,<7 ; extra == 'test-tools'
|
|
@@ -95,6 +97,33 @@ This enables the `route` label for Prometheus HTTP metrics.
|
|
|
95
97
|
|
|
96
98
|
5. To enable the `/metrics` endpoint, set the `PROMETHEUS_ENABLED` setting to `True`.
|
|
97
99
|
|
|
100
|
+
### Startup commands
|
|
101
|
+
|
|
102
|
+
`common.core` registers composite startup verbs on the `flagsmith` command, so a container entrypoint can sequence startup itself rather than via a shell script:
|
|
103
|
+
|
|
104
|
+
- `flagsmith serve` — wait for the database, then start the API.
|
|
105
|
+
- `flagsmith migrate` — migrate each configured database, then create the cache table. A bare invocation runs the full sequence; `flagsmith migrate <app> <name>` defers to Django for targeted migrations.
|
|
106
|
+
- `flagsmith run-task-processor` — migrate, wait for migrations to be applied, then start the Task Processor.
|
|
107
|
+
- `flagsmith migrate-and-serve` — migrate, run any configured startup commands, then start the API.
|
|
108
|
+
|
|
109
|
+
The verbs are configured through these settings:
|
|
110
|
+
|
|
111
|
+
| Setting | Default | Purpose |
|
|
112
|
+
| --- | --- | --- |
|
|
113
|
+
| `FLAGSMITH_MIGRATE_DATABASES` | `["default"]` | Database aliases the `migrate` step applies, in order. |
|
|
114
|
+
| `FLAGSMITH_WAIT_FOR_MIGRATIONS_DATABASES` | `["default"]` | Database aliases `run-task-processor` waits on before starting. |
|
|
115
|
+
| `FLAGSMITH_STARTUP_COMMANDS` | `[]` | Management commands run, in order, between migrate and serve in `migrate-and-serve`. |
|
|
116
|
+
|
|
117
|
+
…and these environment variables:
|
|
118
|
+
|
|
119
|
+
| Environment variable | Default | Purpose |
|
|
120
|
+
| --- | --- | --- |
|
|
121
|
+
| `SKIP_WAIT_FOR_DB` | unset | When set, skip waiting for the database. |
|
|
122
|
+
| `TASK_PROCESSOR_NUM_THREADS` | `5` | Number of worker threads. |
|
|
123
|
+
| `TASK_PROCESSOR_SLEEP_INTERVAL_MS` | `500` | Millis each worker waits before checking for new tasks (falls back to `TASK_PROCESSOR_SLEEP_INTERVAL`). |
|
|
124
|
+
| `TASK_PROCESSOR_GRACE_PERIOD_MS` | `20000` | Millis before a running task is considered stuck. |
|
|
125
|
+
| `TASK_PROCESSOR_QUEUE_POP_SIZE` | `10` | Tasks each worker pops from the queue per cycle. |
|
|
126
|
+
|
|
98
127
|
### Pre-commit hooks
|
|
99
128
|
|
|
100
129
|
This repo provides a [`flagsmith-lint-tests`](.pre-commit-hooks.yaml) hook that enforces test conventions:
|
|
@@ -166,7 +195,8 @@ OTel instrumentation is opt-in, controlled by environment variables:
|
|
|
166
195
|
|
|
167
196
|
| Variable | Description | Default |
|
|
168
197
|
| --------------------------------- | --------------------------------------------------------------------------------------------------------------------- | --------------- |
|
|
169
|
-
| `OTEL_EXPORTER_OTLP_ENDPOINT` | Base OTLP endpoint (e.g. `http://collector:4318`). If unset, no OTel setup occurs.
|
|
198
|
+
| `OTEL_EXPORTER_OTLP_ENDPOINT` | Base OTLP endpoint (e.g. `http://collector:4318` for HTTP, `http://collector:4317` for gRPC). If unset, no OTel setup occurs. | _(disabled)_ |
|
|
199
|
+
| `OTEL_EXPORTER_OTLP_PROTOCOL` | OTLP transport: `grpc` or `http/protobuf` (default). | `http/protobuf` |
|
|
170
200
|
| `OTEL_SERVICE_NAME` | The `service.name` resource attribute. Defaults to `flagsmith-task-processor` when running the task processor. | `flagsmith-api` |
|
|
171
201
|
| `OTEL_TRACING_EXCLUDED_URL_PATHS` | Comma-separated URL paths to exclude from tracing (e.g. `health/liveness,health/readiness`). | _(none)_ |
|
|
172
202
|
|
|
@@ -176,7 +206,7 @@ Standard `OTEL_*` env vars (e.g. `OTEL_RESOURCE_ATTRIBUTES`, `OTEL_EXPORTER_OTLP
|
|
|
176
206
|
|
|
177
207
|
When `OTEL_EXPORTER_OTLP_ENDPOINT` is set, `ensure_cli_env()` sets up:
|
|
178
208
|
|
|
179
|
-
- **Tracing**: `TracerProvider` with OTLP
|
|
209
|
+
- **Tracing**: `TracerProvider` with OTLP span export (HTTP or gRPC, per `OTEL_EXPORTER_OTLP_PROTOCOL`), W3C `TraceContext` + `Baggage` propagation, and auto-instrumentation for:
|
|
180
210
|
- **Django** (`DjangoInstrumentor`): creates a root span per HTTP request with span names formatted as `{METHOD} {route_template}` (e.g. `GET /api/v1/projects/{pk}/`).
|
|
181
211
|
- **psycopg2** (`Psycopg2Instrumentor`): creates child spans for each SQL query with `db.system`, `db.statement`, and `db.name` attributes. SQL commenter is enabled, adding trace context as SQL comments for database-side correlation.
|
|
182
212
|
- **Redis** (`RedisInstrumentor`): creates child spans for each Redis command with `db.system` and `db.statement` attributes.
|
|
@@ -35,6 +35,33 @@ This enables the `route` label for Prometheus HTTP metrics.
|
|
|
35
35
|
|
|
36
36
|
5. To enable the `/metrics` endpoint, set the `PROMETHEUS_ENABLED` setting to `True`.
|
|
37
37
|
|
|
38
|
+
### Startup commands
|
|
39
|
+
|
|
40
|
+
`common.core` registers composite startup verbs on the `flagsmith` command, so a container entrypoint can sequence startup itself rather than via a shell script:
|
|
41
|
+
|
|
42
|
+
- `flagsmith serve` — wait for the database, then start the API.
|
|
43
|
+
- `flagsmith migrate` — migrate each configured database, then create the cache table. A bare invocation runs the full sequence; `flagsmith migrate <app> <name>` defers to Django for targeted migrations.
|
|
44
|
+
- `flagsmith run-task-processor` — migrate, wait for migrations to be applied, then start the Task Processor.
|
|
45
|
+
- `flagsmith migrate-and-serve` — migrate, run any configured startup commands, then start the API.
|
|
46
|
+
|
|
47
|
+
The verbs are configured through these settings:
|
|
48
|
+
|
|
49
|
+
| Setting | Default | Purpose |
|
|
50
|
+
| --- | --- | --- |
|
|
51
|
+
| `FLAGSMITH_MIGRATE_DATABASES` | `["default"]` | Database aliases the `migrate` step applies, in order. |
|
|
52
|
+
| `FLAGSMITH_WAIT_FOR_MIGRATIONS_DATABASES` | `["default"]` | Database aliases `run-task-processor` waits on before starting. |
|
|
53
|
+
| `FLAGSMITH_STARTUP_COMMANDS` | `[]` | Management commands run, in order, between migrate and serve in `migrate-and-serve`. |
|
|
54
|
+
|
|
55
|
+
…and these environment variables:
|
|
56
|
+
|
|
57
|
+
| Environment variable | Default | Purpose |
|
|
58
|
+
| --- | --- | --- |
|
|
59
|
+
| `SKIP_WAIT_FOR_DB` | unset | When set, skip waiting for the database. |
|
|
60
|
+
| `TASK_PROCESSOR_NUM_THREADS` | `5` | Number of worker threads. |
|
|
61
|
+
| `TASK_PROCESSOR_SLEEP_INTERVAL_MS` | `500` | Millis each worker waits before checking for new tasks (falls back to `TASK_PROCESSOR_SLEEP_INTERVAL`). |
|
|
62
|
+
| `TASK_PROCESSOR_GRACE_PERIOD_MS` | `20000` | Millis before a running task is considered stuck. |
|
|
63
|
+
| `TASK_PROCESSOR_QUEUE_POP_SIZE` | `10` | Tasks each worker pops from the queue per cycle. |
|
|
64
|
+
|
|
38
65
|
### Pre-commit hooks
|
|
39
66
|
|
|
40
67
|
This repo provides a [`flagsmith-lint-tests`](.pre-commit-hooks.yaml) hook that enforces test conventions:
|
|
@@ -106,7 +133,8 @@ OTel instrumentation is opt-in, controlled by environment variables:
|
|
|
106
133
|
|
|
107
134
|
| Variable | Description | Default |
|
|
108
135
|
| --------------------------------- | --------------------------------------------------------------------------------------------------------------------- | --------------- |
|
|
109
|
-
| `OTEL_EXPORTER_OTLP_ENDPOINT` | Base OTLP endpoint (e.g. `http://collector:4318`). If unset, no OTel setup occurs.
|
|
136
|
+
| `OTEL_EXPORTER_OTLP_ENDPOINT` | Base OTLP endpoint (e.g. `http://collector:4318` for HTTP, `http://collector:4317` for gRPC). If unset, no OTel setup occurs. | _(disabled)_ |
|
|
137
|
+
| `OTEL_EXPORTER_OTLP_PROTOCOL` | OTLP transport: `grpc` or `http/protobuf` (default). | `http/protobuf` |
|
|
110
138
|
| `OTEL_SERVICE_NAME` | The `service.name` resource attribute. Defaults to `flagsmith-task-processor` when running the task processor. | `flagsmith-api` |
|
|
111
139
|
| `OTEL_TRACING_EXCLUDED_URL_PATHS` | Comma-separated URL paths to exclude from tracing (e.g. `health/liveness,health/readiness`). | _(none)_ |
|
|
112
140
|
|
|
@@ -116,7 +144,7 @@ Standard `OTEL_*` env vars (e.g. `OTEL_RESOURCE_ATTRIBUTES`, `OTEL_EXPORTER_OTLP
|
|
|
116
144
|
|
|
117
145
|
When `OTEL_EXPORTER_OTLP_ENDPOINT` is set, `ensure_cli_env()` sets up:
|
|
118
146
|
|
|
119
|
-
- **Tracing**: `TracerProvider` with OTLP
|
|
147
|
+
- **Tracing**: `TracerProvider` with OTLP span export (HTTP or gRPC, per `OTEL_EXPORTER_OTLP_PROTOCOL`), W3C `TraceContext` + `Baggage` propagation, and auto-instrumentation for:
|
|
120
148
|
- **Django** (`DjangoInstrumentor`): creates a root span per HTTP request with span names formatted as `{METHOD} {route_template}` (e.g. `GET /api/v1/projects/{pk}/`).
|
|
121
149
|
- **psycopg2** (`Psycopg2Instrumentor`): creates child spans for each SQL query with `db.system`, `db.statement`, and `db.name` attributes. SQL commenter is enabled, adding trace context as SQL comments for database-side correlation.
|
|
122
150
|
- **Redis** (`RedisInstrumentor`): creates child spans for each Redis command with `db.system` and `db.statement` attributes.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "flagsmith-common"
|
|
3
|
-
version = "3.
|
|
3
|
+
version = "3.12.0"
|
|
4
4
|
description = "Flagsmith's common library"
|
|
5
5
|
requires-python = ">=3.11,<4.0"
|
|
6
6
|
dependencies = []
|
|
@@ -29,6 +29,7 @@ optional-dependencies = { test-tools = [
|
|
|
29
29
|
"inflection",
|
|
30
30
|
"opentelemetry-api (>=1.25,<2)",
|
|
31
31
|
"opentelemetry-sdk (>=1.25,<2)",
|
|
32
|
+
"opentelemetry-exporter-otlp-proto-grpc (>=1.25,<2)",
|
|
32
33
|
"opentelemetry-exporter-otlp-proto-http (>=1.25,<2)",
|
|
33
34
|
"sentry-sdk (>=2.0.0,<3.0.0)",
|
|
34
35
|
"structlog (>=24.4,<26)",
|
|
@@ -37,6 +38,7 @@ optional-dependencies = { test-tools = [
|
|
|
37
38
|
"backoff (>=2.2.1,<3.0.0)",
|
|
38
39
|
"django (>4,<6)",
|
|
39
40
|
"django-health-check",
|
|
41
|
+
"environs (<16)",
|
|
40
42
|
"opentelemetry-api (>=1.25,<2)",
|
|
41
43
|
"prometheus-client (>=0.0.16)",
|
|
42
44
|
], flagsmith-schemas = [
|
|
@@ -96,7 +98,7 @@ dev = [
|
|
|
96
98
|
"pytest-freezegun (>=0.4.2, <1.0.0)",
|
|
97
99
|
"pytest-httpserver (>=1.1.3, <2.0.0)",
|
|
98
100
|
"pytest-mock (>=3.14.0, <4.0.0)",
|
|
99
|
-
"setuptools (>=
|
|
101
|
+
"setuptools (>=83.0.0, <83.1.0)",
|
|
100
102
|
"types-python-dateutil (>=2.9.0.20250516, <3.0.0)",
|
|
101
103
|
"types-simplejson (>=3.20.0.20250326, <4.0.0)",
|
|
102
104
|
]
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
"""Composite startup verbs for the `flagsmith` entrypoint.
|
|
2
|
+
|
|
3
|
+
These mirror the sequencing that Core API's `run-docker.sh` performed in
|
|
4
|
+
shell, but run in a single process so the Django boot cost is paid once.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import os
|
|
8
|
+
import shlex
|
|
9
|
+
|
|
10
|
+
from django.conf import settings
|
|
11
|
+
from django.core.management import (
|
|
12
|
+
execute_from_command_line as django_execute_from_command_line,
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
WAIT_FOR_MIGRATIONS_TIMEOUT_SECONDS = 30
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def _wait_for_db(
|
|
19
|
+
*,
|
|
20
|
+
wait_for_migrations: bool = False,
|
|
21
|
+
database: str = "default",
|
|
22
|
+
wait_for: int | None = None,
|
|
23
|
+
) -> None:
|
|
24
|
+
if os.environ.get("SKIP_WAIT_FOR_DB"):
|
|
25
|
+
return
|
|
26
|
+
args = ["waitfordb", "--database", database]
|
|
27
|
+
if wait_for is not None:
|
|
28
|
+
args += ["--waitfor", str(wait_for)]
|
|
29
|
+
if wait_for_migrations:
|
|
30
|
+
args.append("--migrations")
|
|
31
|
+
django_execute_from_command_line(["flagsmith", *args])
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def _migrate() -> None:
|
|
35
|
+
_wait_for_db()
|
|
36
|
+
databases: list[str] = getattr(settings, "FLAGSMITH_MIGRATE_DATABASES", ["default"])
|
|
37
|
+
for database in databases:
|
|
38
|
+
django_execute_from_command_line(
|
|
39
|
+
["flagsmith", "migrate", "--database", database]
|
|
40
|
+
)
|
|
41
|
+
django_execute_from_command_line(["flagsmith", "createcachetable"])
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def migrate(argv: list[str], *, prog: str) -> None:
|
|
45
|
+
"""Migrate the configured databases, then create the cache table."""
|
|
46
|
+
if argv:
|
|
47
|
+
django_execute_from_command_line(["flagsmith", "migrate", *argv])
|
|
48
|
+
return
|
|
49
|
+
_migrate()
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def serve(argv: list[str], *, prog: str) -> None:
|
|
53
|
+
"""Wait for the database, then start the API server."""
|
|
54
|
+
_wait_for_db()
|
|
55
|
+
django_execute_from_command_line(["flagsmith", "start", "api", *argv])
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def run_task_processor(argv: list[str], *, prog: str) -> None:
|
|
59
|
+
"""Migrate, wait for migrations to be applied, then start the task processor."""
|
|
60
|
+
_migrate()
|
|
61
|
+
databases: list[str] = getattr(
|
|
62
|
+
settings, "FLAGSMITH_WAIT_FOR_MIGRATIONS_DATABASES", ["default"]
|
|
63
|
+
)
|
|
64
|
+
for database in databases:
|
|
65
|
+
_wait_for_db(
|
|
66
|
+
wait_for_migrations=True,
|
|
67
|
+
database=database,
|
|
68
|
+
wait_for=WAIT_FOR_MIGRATIONS_TIMEOUT_SECONDS,
|
|
69
|
+
)
|
|
70
|
+
django_execute_from_command_line(["flagsmith", "start", "task-processor", *argv])
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def migrate_and_serve(argv: list[str], *, prog: str) -> None:
|
|
74
|
+
"""Migrate, run any configured startup commands, then start the API server."""
|
|
75
|
+
_migrate()
|
|
76
|
+
startup_commands: list[str] = getattr(settings, "FLAGSMITH_STARTUP_COMMANDS", [])
|
|
77
|
+
for command in startup_commands:
|
|
78
|
+
django_execute_from_command_line(["flagsmith", *shlex.split(command)])
|
|
79
|
+
django_execute_from_command_line(["flagsmith", "start", "api", *argv])
|
|
@@ -8,10 +8,12 @@ from tempfile import mkdtemp
|
|
|
8
8
|
from django.core.management import (
|
|
9
9
|
execute_from_command_line as django_execute_from_command_line,
|
|
10
10
|
)
|
|
11
|
-
from environs import Env
|
|
11
|
+
from environs import Env, validate
|
|
12
12
|
|
|
13
|
-
from common.core.cli import healthcheck
|
|
13
|
+
from common.core.cli import healthcheck, run
|
|
14
|
+
from common.core.constants import DEFAULT_OTLP_PROTOCOL
|
|
14
15
|
from common.core.logging import setup_logging
|
|
16
|
+
from common.core.types import OtlpProtocol
|
|
15
17
|
from common.gunicorn.processors import make_gunicorn_access_processor
|
|
16
18
|
|
|
17
19
|
env = Env()
|
|
@@ -63,6 +65,7 @@ def ensure_cli_env() -> typing.Generator[None, None, None]:
|
|
|
63
65
|
build_otel_log_provider,
|
|
64
66
|
build_tracer_provider,
|
|
65
67
|
make_structlog_otel_processor,
|
|
68
|
+
resolve_otlp_export_endpoints,
|
|
66
69
|
setup_tracing,
|
|
67
70
|
)
|
|
68
71
|
|
|
@@ -72,17 +75,31 @@ def ensure_cli_env() -> typing.Generator[None, None, None]:
|
|
|
72
75
|
else "flagsmith-api"
|
|
73
76
|
)
|
|
74
77
|
service_name = env.str("OTEL_SERVICE_NAME", default_service_name)
|
|
78
|
+
otel_protocol = typing.cast(
|
|
79
|
+
OtlpProtocol,
|
|
80
|
+
env.str(
|
|
81
|
+
"OTEL_EXPORTER_OTLP_PROTOCOL",
|
|
82
|
+
DEFAULT_OTLP_PROTOCOL,
|
|
83
|
+
validate=validate.OneOf(typing.get_args(OtlpProtocol)),
|
|
84
|
+
),
|
|
85
|
+
)
|
|
86
|
+
traces_endpoint, logs_endpoint = resolve_otlp_export_endpoints(
|
|
87
|
+
otel_endpoint,
|
|
88
|
+
otel_protocol,
|
|
89
|
+
)
|
|
75
90
|
log_provider = build_otel_log_provider(
|
|
76
|
-
endpoint=
|
|
91
|
+
endpoint=logs_endpoint,
|
|
77
92
|
service_name=service_name,
|
|
93
|
+
protocol=otel_protocol,
|
|
78
94
|
)
|
|
79
95
|
otel_processors = [
|
|
80
96
|
add_otel_trace_context,
|
|
81
97
|
make_structlog_otel_processor(log_provider),
|
|
82
98
|
]
|
|
83
99
|
tracer_provider = build_tracer_provider(
|
|
84
|
-
endpoint=
|
|
100
|
+
endpoint=traces_endpoint,
|
|
85
101
|
service_name=service_name,
|
|
102
|
+
protocol=otel_protocol,
|
|
86
103
|
)
|
|
87
104
|
excluded_urls = env.str("OTEL_TRACING_EXCLUDED_URL_PATHS", None)
|
|
88
105
|
ctx.enter_context(setup_tracing(tracer_provider, excluded_urls=excluded_urls))
|
|
@@ -118,6 +135,11 @@ def execute_from_command_line(argv: list[str]) -> None:
|
|
|
118
135
|
# Backwards compatibility for task-processor health checks
|
|
119
136
|
# See https://github.com/Flagsmith/flagsmith-task-processor/issues/24
|
|
120
137
|
"checktaskprocessorthreadhealth": healthcheck.main,
|
|
138
|
+
# Composite startup verbs, formerly run-docker.sh
|
|
139
|
+
"serve": run.serve,
|
|
140
|
+
"migrate": run.migrate,
|
|
141
|
+
"run-task-processor": run.run_task_processor,
|
|
142
|
+
"migrate-and-serve": run.migrate_and_serve,
|
|
121
143
|
}[subcommand]
|
|
122
144
|
except (IndexError, KeyError):
|
|
123
145
|
logger.info("Invoking Django")
|
|
@@ -11,26 +11,37 @@ from opentelemetry import baggage, trace
|
|
|
11
11
|
from opentelemetry import context as otel_context
|
|
12
12
|
from opentelemetry._logs import SeverityNumber
|
|
13
13
|
from opentelemetry.baggage.propagation import W3CBaggagePropagator
|
|
14
|
+
from opentelemetry.exporter.otlp.proto.grpc._log_exporter import (
|
|
15
|
+
OTLPLogExporter as GrpcOTLPLogExporter,
|
|
16
|
+
)
|
|
17
|
+
from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import (
|
|
18
|
+
OTLPSpanExporter as GrpcOTLPSpanExporter,
|
|
19
|
+
)
|
|
14
20
|
from opentelemetry.exporter.otlp.proto.http._log_exporter import (
|
|
15
|
-
OTLPLogExporter,
|
|
21
|
+
OTLPLogExporter as HttpOTLPLogExporter,
|
|
16
22
|
)
|
|
17
23
|
from opentelemetry.exporter.otlp.proto.http.trace_exporter import (
|
|
18
|
-
OTLPSpanExporter,
|
|
24
|
+
OTLPSpanExporter as HttpOTLPSpanExporter,
|
|
19
25
|
)
|
|
20
26
|
from opentelemetry.propagate import set_global_textmap
|
|
21
27
|
from opentelemetry.propagators.composite import CompositePropagator
|
|
22
28
|
from opentelemetry.propagators.textmap import TextMapPropagator
|
|
23
29
|
from opentelemetry.sdk._logs import LoggerProvider
|
|
24
|
-
from opentelemetry.sdk._logs.export import
|
|
30
|
+
from opentelemetry.sdk._logs.export import (
|
|
31
|
+
BatchLogRecordProcessor,
|
|
32
|
+
LogRecordExporter,
|
|
33
|
+
)
|
|
25
34
|
from opentelemetry.sdk.resources import Resource
|
|
26
35
|
from opentelemetry.sdk.trace import TracerProvider
|
|
27
|
-
from opentelemetry.sdk.trace.export import BatchSpanProcessor
|
|
36
|
+
from opentelemetry.sdk.trace.export import BatchSpanProcessor, SpanExporter
|
|
28
37
|
from opentelemetry.trace.propagation.tracecontext import (
|
|
29
38
|
TraceContextTextMapPropagator,
|
|
30
39
|
)
|
|
31
40
|
from opentelemetry.util.types import AnyValue, Attributes
|
|
32
41
|
from structlog.typing import EventDict, Processor
|
|
33
42
|
|
|
43
|
+
from common.core.types import OtlpProtocol
|
|
44
|
+
|
|
34
45
|
_SEVERITY_MAP: dict[str, SeverityNumber] = {
|
|
35
46
|
"debug": SeverityNumber.DEBUG,
|
|
36
47
|
"info": SeverityNumber.INFO,
|
|
@@ -51,6 +62,17 @@ _RESERVED_KEYS = frozenset(
|
|
|
51
62
|
)
|
|
52
63
|
|
|
53
64
|
|
|
65
|
+
def resolve_otlp_export_endpoints(
|
|
66
|
+
base_endpoint: str,
|
|
67
|
+
protocol: OtlpProtocol,
|
|
68
|
+
) -> tuple[str, str]:
|
|
69
|
+
"""Resolve trace and log exporter endpoints from a base OTLP endpoint."""
|
|
70
|
+
normalised_base = base_endpoint.rstrip("/")
|
|
71
|
+
if protocol == "grpc":
|
|
72
|
+
return normalised_base, normalised_base
|
|
73
|
+
return f"{normalised_base}/v1/traces", f"{normalised_base}/v1/logs"
|
|
74
|
+
|
|
75
|
+
|
|
54
76
|
def get_otel_event_name(*, logger_name: str | None, body: str) -> str:
|
|
55
77
|
"""Build the event name that reaches OTel from a structlog `(logger, event)`.
|
|
56
78
|
|
|
@@ -153,20 +175,38 @@ def map_value_to_otel_value(value: object) -> str | int | float | bool:
|
|
|
153
175
|
return json.dumps(value, default=str)
|
|
154
176
|
|
|
155
177
|
|
|
156
|
-
def build_otel_log_provider(
|
|
157
|
-
|
|
178
|
+
def build_otel_log_provider(
|
|
179
|
+
*,
|
|
180
|
+
endpoint: str,
|
|
181
|
+
service_name: str,
|
|
182
|
+
protocol: OtlpProtocol,
|
|
183
|
+
) -> LoggerProvider:
|
|
184
|
+
"""Create and configure an OTel LoggerProvider with OTLP export."""
|
|
158
185
|
resource = Resource.create({"service.name": service_name})
|
|
159
186
|
provider = LoggerProvider(resource=resource)
|
|
160
|
-
exporter
|
|
187
|
+
exporter: LogRecordExporter
|
|
188
|
+
if protocol == "grpc":
|
|
189
|
+
exporter = GrpcOTLPLogExporter(endpoint=endpoint)
|
|
190
|
+
else:
|
|
191
|
+
exporter = HttpOTLPLogExporter(endpoint=endpoint)
|
|
161
192
|
provider.add_log_record_processor(BatchLogRecordProcessor(exporter))
|
|
162
193
|
return provider
|
|
163
194
|
|
|
164
195
|
|
|
165
|
-
def build_tracer_provider(
|
|
166
|
-
|
|
196
|
+
def build_tracer_provider(
|
|
197
|
+
*,
|
|
198
|
+
endpoint: str,
|
|
199
|
+
service_name: str,
|
|
200
|
+
protocol: OtlpProtocol,
|
|
201
|
+
) -> TracerProvider:
|
|
202
|
+
"""Create a TracerProvider with OTLP export."""
|
|
167
203
|
resource = Resource.create({"service.name": service_name})
|
|
168
204
|
tracer_provider = TracerProvider(resource=resource)
|
|
169
|
-
span_exporter
|
|
205
|
+
span_exporter: SpanExporter
|
|
206
|
+
if protocol == "grpc":
|
|
207
|
+
span_exporter = GrpcOTLPSpanExporter(endpoint=endpoint)
|
|
208
|
+
else:
|
|
209
|
+
span_exporter = HttpOTLPSpanExporter(endpoint=endpoint)
|
|
170
210
|
tracer_provider.add_span_processor(BatchSpanProcessor(span_exporter))
|
|
171
211
|
return tracer_provider
|
|
172
212
|
|
|
@@ -1,14 +1,25 @@
|
|
|
1
1
|
import argparse
|
|
2
2
|
import inspect
|
|
3
3
|
import logging
|
|
4
|
+
import os
|
|
4
5
|
from contextlib import contextmanager
|
|
5
6
|
from typing import Any, Generator
|
|
6
7
|
|
|
8
|
+
from environs import Env
|
|
9
|
+
|
|
10
|
+
from task_processor.constants import (
|
|
11
|
+
DEFAULT_TASK_PROCESSOR_GRACE_PERIOD_MS,
|
|
12
|
+
DEFAULT_TASK_PROCESSOR_NUM_THREADS,
|
|
13
|
+
DEFAULT_TASK_PROCESSOR_QUEUE_POP_SIZE,
|
|
14
|
+
DEFAULT_TASK_PROCESSOR_SLEEP_INTERVAL_MS,
|
|
15
|
+
)
|
|
7
16
|
from task_processor.threads import TaskRunnerCoordinator
|
|
8
17
|
from task_processor.types import TaskCallable, TaskProcessorConfig
|
|
9
18
|
|
|
10
19
|
logger = logging.getLogger(__name__)
|
|
11
20
|
|
|
21
|
+
env = Env()
|
|
22
|
+
|
|
12
23
|
|
|
13
24
|
def get_task_identifier_from_function(
|
|
14
25
|
function: TaskCallable[Any],
|
|
@@ -24,25 +35,41 @@ def add_arguments(parser: argparse.ArgumentParser) -> None:
|
|
|
24
35
|
"--numthreads",
|
|
25
36
|
type=int,
|
|
26
37
|
help="Number of worker threads to run.",
|
|
27
|
-
default=
|
|
38
|
+
default=env.int(
|
|
39
|
+
"TASK_PROCESSOR_NUM_THREADS",
|
|
40
|
+
default=DEFAULT_TASK_PROCESSOR_NUM_THREADS,
|
|
41
|
+
),
|
|
28
42
|
)
|
|
29
43
|
parser.add_argument(
|
|
30
44
|
"--sleepintervalms",
|
|
31
45
|
type=int,
|
|
32
46
|
help="Number of millis each worker waits before checking for new tasks",
|
|
33
|
-
default=
|
|
47
|
+
default=(
|
|
48
|
+
env.int("TASK_PROCESSOR_SLEEP_INTERVAL_MS")
|
|
49
|
+
if "TASK_PROCESSOR_SLEEP_INTERVAL_MS" in os.environ
|
|
50
|
+
else env.int(
|
|
51
|
+
"TASK_PROCESSOR_SLEEP_INTERVAL",
|
|
52
|
+
default=DEFAULT_TASK_PROCESSOR_SLEEP_INTERVAL_MS,
|
|
53
|
+
)
|
|
54
|
+
),
|
|
34
55
|
)
|
|
35
56
|
parser.add_argument(
|
|
36
57
|
"--graceperiodms",
|
|
37
58
|
type=int,
|
|
38
59
|
help="Number of millis before running task is considered 'stuck'.",
|
|
39
|
-
default=
|
|
60
|
+
default=env.int(
|
|
61
|
+
"TASK_PROCESSOR_GRACE_PERIOD_MS",
|
|
62
|
+
default=DEFAULT_TASK_PROCESSOR_GRACE_PERIOD_MS,
|
|
63
|
+
),
|
|
40
64
|
)
|
|
41
65
|
parser.add_argument(
|
|
42
66
|
"--queuepopsize",
|
|
43
67
|
type=int,
|
|
44
68
|
help="Number of tasks each worker will pop from the queue on each cycle.",
|
|
45
|
-
default=
|
|
69
|
+
default=env.int(
|
|
70
|
+
"TASK_PROCESSOR_QUEUE_POP_SIZE",
|
|
71
|
+
default=DEFAULT_TASK_PROCESSOR_QUEUE_POP_SIZE,
|
|
72
|
+
),
|
|
46
73
|
)
|
|
47
74
|
|
|
48
75
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/common/core/management/commands/__init__.py
RENAMED
|
File without changes
|
{flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/common/core/management/commands/docgen.py
RENAMED
|
File without changes
|
{flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/common/core/management/commands/start.py
RENAMED
|
File without changes
|
{flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/common/core/management/commands/waitfordb.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/common/core/templates/docgen-events.md
RENAMED
|
File without changes
|
{flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/common/core/templates/docgen-metrics.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/common/features/multivariate/__init__.py
RENAMED
|
File without changes
|
{flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/common/features/multivariate/serializers.py
RENAMED
|
File without changes
|
|
File without changes
|
{flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/common/features/versioning/__init__.py
RENAMED
|
File without changes
|
{flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/common/features/versioning/serializers.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/common/migrations/helpers/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/task_processor/migrations/0001_initial.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/task_processor/migrations/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{flagsmith_common-3.10.1 → flagsmith_common-3.12.0}/src/task_processor/migrations/sql/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|