flagsmith-common 2.0.0__tar.gz → 2.1.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-2.0.0 → flagsmith_common-2.1.0}/PKG-INFO +1 -1
- {flagsmith_common-2.0.0 → flagsmith_common-2.1.0}/pyproject.toml +1 -1
- flagsmith_common-2.1.0/src/common/core/__init__.py +6 -0
- {flagsmith_common-2.0.0 → flagsmith_common-2.1.0}/src/common/core/utils.py +66 -2
- flagsmith_common-2.0.0/src/task_processor/migrations/sql/__init__.py +0 -0
- {flagsmith_common-2.0.0 → flagsmith_common-2.1.0}/LICENSE +0 -0
- {flagsmith_common-2.0.0 → flagsmith_common-2.1.0}/README.md +0 -0
- {flagsmith_common-2.0.0 → flagsmith_common-2.1.0}/src/common/__init__.py +0 -0
- {flagsmith_common-2.0.0 → flagsmith_common-2.1.0}/src/common/core/app.py +0 -0
- {flagsmith_common-2.0.0/src/common/core → flagsmith_common-2.1.0/src/common/core/cli}/__init__.py +0 -0
- {flagsmith_common-2.0.0 → flagsmith_common-2.1.0}/src/common/core/cli/healthcheck.py +0 -0
- {flagsmith_common-2.0.0 → flagsmith_common-2.1.0}/src/common/core/logging.py +0 -0
- {flagsmith_common-2.0.0 → flagsmith_common-2.1.0}/src/common/core/main.py +0 -0
- {flagsmith_common-2.0.0/src/common/core/cli → flagsmith_common-2.1.0/src/common/core/management}/__init__.py +0 -0
- {flagsmith_common-2.0.0/src/common/core/management → flagsmith_common-2.1.0/src/common/core/management/commands}/__init__.py +0 -0
- {flagsmith_common-2.0.0 → flagsmith_common-2.1.0}/src/common/core/management/commands/docgen.py +0 -0
- {flagsmith_common-2.0.0 → flagsmith_common-2.1.0}/src/common/core/management/commands/start.py +0 -0
- {flagsmith_common-2.0.0 → flagsmith_common-2.1.0}/src/common/core/management/commands/waitfordb.py +0 -0
- {flagsmith_common-2.0.0 → flagsmith_common-2.1.0}/src/common/core/metrics.py +0 -0
- {flagsmith_common-2.0.0 → flagsmith_common-2.1.0}/src/common/core/middleware.py +0 -0
- {flagsmith_common-2.0.0 → flagsmith_common-2.1.0}/src/common/core/templates/docgen-metrics.md +0 -0
- {flagsmith_common-2.0.0 → flagsmith_common-2.1.0}/src/common/core/urls.py +0 -0
- {flagsmith_common-2.0.0 → flagsmith_common-2.1.0}/src/common/core/views.py +0 -0
- {flagsmith_common-2.0.0 → flagsmith_common-2.1.0}/src/common/environments/permissions.py +0 -0
- {flagsmith_common-2.0.0/src/common/core/management/commands → flagsmith_common-2.1.0/src/common/features}/__init__.py +0 -0
- {flagsmith_common-2.0.0/src/common/features → flagsmith_common-2.1.0/src/common/features/multivariate}/__init__.py +0 -0
- {flagsmith_common-2.0.0 → flagsmith_common-2.1.0}/src/common/features/multivariate/serializers.py +0 -0
- {flagsmith_common-2.0.0 → flagsmith_common-2.1.0}/src/common/features/serializers.py +0 -0
- {flagsmith_common-2.0.0/src/common/features/multivariate → flagsmith_common-2.1.0/src/common/features/versioning}/__init__.py +0 -0
- {flagsmith_common-2.0.0 → flagsmith_common-2.1.0}/src/common/features/versioning/serializers.py +0 -0
- {flagsmith_common-2.0.0/src/common/features/versioning → flagsmith_common-2.1.0/src/common/gunicorn}/__init__.py +0 -0
- {flagsmith_common-2.0.0 → flagsmith_common-2.1.0}/src/common/gunicorn/conf.py +0 -0
- {flagsmith_common-2.0.0 → flagsmith_common-2.1.0}/src/common/gunicorn/constants.py +0 -0
- {flagsmith_common-2.0.0 → flagsmith_common-2.1.0}/src/common/gunicorn/logging.py +0 -0
- {flagsmith_common-2.0.0 → flagsmith_common-2.1.0}/src/common/gunicorn/metrics.py +0 -0
- {flagsmith_common-2.0.0 → flagsmith_common-2.1.0}/src/common/gunicorn/middleware.py +0 -0
- {flagsmith_common-2.0.0 → flagsmith_common-2.1.0}/src/common/gunicorn/utils.py +0 -0
- {flagsmith_common-2.0.0/src/common/gunicorn → flagsmith_common-2.1.0/src/common/migrations}/__init__.py +0 -0
- {flagsmith_common-2.0.0 → flagsmith_common-2.1.0}/src/common/migrations/helpers/__init__.py +0 -0
- {flagsmith_common-2.0.0 → flagsmith_common-2.1.0}/src/common/migrations/helpers/postgres_helpers.py +0 -0
- {flagsmith_common-2.0.0 → flagsmith_common-2.1.0}/src/common/organisations/permissions.py +0 -0
- {flagsmith_common-2.0.0 → flagsmith_common-2.1.0}/src/common/projects/permissions.py +0 -0
- {flagsmith_common-2.0.0 → flagsmith_common-2.1.0}/src/common/prometheus/__init__.py +0 -0
- {flagsmith_common-2.0.0 → flagsmith_common-2.1.0}/src/common/prometheus/utils.py +0 -0
- {flagsmith_common-2.0.0 → flagsmith_common-2.1.0}/src/common/py.typed +0 -0
- {flagsmith_common-2.0.0 → flagsmith_common-2.1.0}/src/common/test_tools/__init__.py +0 -0
- {flagsmith_common-2.0.0 → flagsmith_common-2.1.0}/src/common/test_tools/plugin.py +0 -0
- {flagsmith_common-2.0.0 → flagsmith_common-2.1.0}/src/common/test_tools/types.py +0 -0
- {flagsmith_common-2.0.0 → flagsmith_common-2.1.0}/src/common/test_tools/utils.py +0 -0
- {flagsmith_common-2.0.0 → flagsmith_common-2.1.0}/src/common/types.py +0 -0
- {flagsmith_common-2.0.0/src/common/migrations → flagsmith_common-2.1.0/src/task_processor}/__init__.py +0 -0
- {flagsmith_common-2.0.0 → flagsmith_common-2.1.0}/src/task_processor/admin.py +0 -0
- {flagsmith_common-2.0.0 → flagsmith_common-2.1.0}/src/task_processor/apps.py +0 -0
- {flagsmith_common-2.0.0 → flagsmith_common-2.1.0}/src/task_processor/decorators.py +0 -0
- {flagsmith_common-2.0.0 → flagsmith_common-2.1.0}/src/task_processor/exceptions.py +0 -0
- {flagsmith_common-2.0.0 → flagsmith_common-2.1.0}/src/task_processor/health.py +0 -0
- {flagsmith_common-2.0.0 → flagsmith_common-2.1.0}/src/task_processor/managers.py +0 -0
- {flagsmith_common-2.0.0 → flagsmith_common-2.1.0}/src/task_processor/metrics.py +0 -0
- {flagsmith_common-2.0.0 → flagsmith_common-2.1.0}/src/task_processor/migrations/0001_initial.py +0 -0
- {flagsmith_common-2.0.0 → flagsmith_common-2.1.0}/src/task_processor/migrations/0002_healthcheckmodel.py +0 -0
- {flagsmith_common-2.0.0 → flagsmith_common-2.1.0}/src/task_processor/migrations/0003_add_completed_to_task.py +0 -0
- {flagsmith_common-2.0.0 → flagsmith_common-2.1.0}/src/task_processor/migrations/0004_recreate_task_indexes.py +0 -0
- {flagsmith_common-2.0.0 → flagsmith_common-2.1.0}/src/task_processor/migrations/0005_update_conditional_index_conditions.py +0 -0
- {flagsmith_common-2.0.0 → flagsmith_common-2.1.0}/src/task_processor/migrations/0006_auto_20230221_0802.py +0 -0
- {flagsmith_common-2.0.0 → flagsmith_common-2.1.0}/src/task_processor/migrations/0007_add_is_locked.py +0 -0
- {flagsmith_common-2.0.0 → flagsmith_common-2.1.0}/src/task_processor/migrations/0008_add_get_task_to_process_function.py +0 -0
- {flagsmith_common-2.0.0 → flagsmith_common-2.1.0}/src/task_processor/migrations/0009_add_recurring_task_run_first_run_at.py +0 -0
- {flagsmith_common-2.0.0 → flagsmith_common-2.1.0}/src/task_processor/migrations/0010_task_priority.py +0 -0
- {flagsmith_common-2.0.0 → flagsmith_common-2.1.0}/src/task_processor/migrations/0011_add_priority_to_get_tasks_to_process.py +0 -0
- {flagsmith_common-2.0.0 → flagsmith_common-2.1.0}/src/task_processor/migrations/0012_add_locked_at_and_timeout.py +0 -0
- {flagsmith_common-2.0.0 → flagsmith_common-2.1.0}/src/task_processor/migrations/0013_add_last_picked_at.py +0 -0
- {flagsmith_common-2.0.0/src/task_processor → flagsmith_common-2.1.0/src/task_processor/migrations}/__init__.py +0 -0
- {flagsmith_common-2.0.0 → flagsmith_common-2.1.0}/src/task_processor/migrations/sql/0008_get_recurring_tasks_to_process.sql +0 -0
- {flagsmith_common-2.0.0 → flagsmith_common-2.1.0}/src/task_processor/migrations/sql/0008_get_tasks_to_process.sql +0 -0
- {flagsmith_common-2.0.0 → flagsmith_common-2.1.0}/src/task_processor/migrations/sql/0011_get_tasks_to_process.sql +0 -0
- {flagsmith_common-2.0.0 → flagsmith_common-2.1.0}/src/task_processor/migrations/sql/0012_get_recurringtasks_to_process.sql +0 -0
- {flagsmith_common-2.0.0 → flagsmith_common-2.1.0}/src/task_processor/migrations/sql/0013_get_recurringtasks_to_process.sql +0 -0
- {flagsmith_common-2.0.0/src/task_processor/migrations → flagsmith_common-2.1.0/src/task_processor/migrations/sql}/__init__.py +0 -0
- {flagsmith_common-2.0.0 → flagsmith_common-2.1.0}/src/task_processor/models.py +0 -0
- {flagsmith_common-2.0.0 → flagsmith_common-2.1.0}/src/task_processor/monitoring.py +0 -0
- {flagsmith_common-2.0.0 → flagsmith_common-2.1.0}/src/task_processor/processor.py +0 -0
- {flagsmith_common-2.0.0 → flagsmith_common-2.1.0}/src/task_processor/py.typed +0 -0
- {flagsmith_common-2.0.0 → flagsmith_common-2.1.0}/src/task_processor/routers.py +0 -0
- {flagsmith_common-2.0.0 → flagsmith_common-2.1.0}/src/task_processor/serializers.py +0 -0
- {flagsmith_common-2.0.0 → flagsmith_common-2.1.0}/src/task_processor/task_registry.py +0 -0
- {flagsmith_common-2.0.0 → flagsmith_common-2.1.0}/src/task_processor/task_run_method.py +0 -0
- {flagsmith_common-2.0.0 → flagsmith_common-2.1.0}/src/task_processor/tasks.py +0 -0
- {flagsmith_common-2.0.0 → flagsmith_common-2.1.0}/src/task_processor/threads.py +0 -0
- {flagsmith_common-2.0.0 → flagsmith_common-2.1.0}/src/task_processor/types.py +0 -0
- {flagsmith_common-2.0.0 → flagsmith_common-2.1.0}/src/task_processor/urls.py +0 -0
- {flagsmith_common-2.0.0 → flagsmith_common-2.1.0}/src/task_processor/utils.py +0 -0
- {flagsmith_common-2.0.0 → flagsmith_common-2.1.0}/src/task_processor/views.py +0 -0
|
@@ -1,16 +1,30 @@
|
|
|
1
1
|
import json
|
|
2
|
+
import logging
|
|
2
3
|
import pathlib
|
|
4
|
+
import random
|
|
3
5
|
from functools import lru_cache
|
|
4
|
-
from
|
|
6
|
+
from itertools import cycle
|
|
7
|
+
from typing import Iterator, Literal, NotRequired, TypedDict, TypeVar
|
|
5
8
|
|
|
6
9
|
from django.conf import settings
|
|
7
10
|
from django.contrib.auth import get_user_model
|
|
8
11
|
from django.contrib.auth.models import AbstractBaseUser
|
|
9
|
-
from django.db
|
|
12
|
+
from django.db import connections
|
|
13
|
+
from django.db.models import Manager, Model
|
|
14
|
+
from django.db.utils import OperationalError
|
|
15
|
+
|
|
16
|
+
from common.core import ReplicaReadStrategy
|
|
17
|
+
|
|
18
|
+
logger = logging.getLogger(__name__)
|
|
10
19
|
|
|
11
20
|
UNKNOWN = "unknown"
|
|
12
21
|
VERSIONS_INFO_FILE_LOCATION = ".versions.json"
|
|
13
22
|
|
|
23
|
+
ManagerType = TypeVar("ManagerType", bound=Manager[Model])
|
|
24
|
+
|
|
25
|
+
ReplicaNamePrefix = Literal["replica_", "cross_region_replica_"]
|
|
26
|
+
_replica_sequential_names_by_prefix: dict[ReplicaNamePrefix, Iterator[str]] = {}
|
|
27
|
+
|
|
14
28
|
|
|
15
29
|
class SelfHostedData(TypedDict):
|
|
16
30
|
has_users: bool
|
|
@@ -114,3 +128,53 @@ def get_file_contents(file_path: str) -> str | None:
|
|
|
114
128
|
return f.read().replace("\n", "")
|
|
115
129
|
except FileNotFoundError:
|
|
116
130
|
return None
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
def using_database_replica(
|
|
134
|
+
manager: ManagerType,
|
|
135
|
+
replica_prefix: ReplicaNamePrefix = "replica_",
|
|
136
|
+
) -> ManagerType:
|
|
137
|
+
"""Attempts to bind a manager to a healthy database replica"""
|
|
138
|
+
local_replicas = [name for name in connections if name.startswith(replica_prefix)]
|
|
139
|
+
|
|
140
|
+
if not local_replicas:
|
|
141
|
+
logger.info("No replicas set up.")
|
|
142
|
+
return manager
|
|
143
|
+
|
|
144
|
+
chosen_replica = None
|
|
145
|
+
|
|
146
|
+
if settings.REPLICA_READ_STRATEGY == ReplicaReadStrategy.SEQUENTIAL:
|
|
147
|
+
sequence = _replica_sequential_names_by_prefix.setdefault(
|
|
148
|
+
replica_prefix, cycle(local_replicas)
|
|
149
|
+
)
|
|
150
|
+
for _ in range(len(local_replicas)):
|
|
151
|
+
attempted_replica = next(sequence)
|
|
152
|
+
try:
|
|
153
|
+
connections[attempted_replica].ensure_connection()
|
|
154
|
+
chosen_replica = attempted_replica
|
|
155
|
+
break
|
|
156
|
+
except OperationalError:
|
|
157
|
+
logger.exception(f"Replica '{attempted_replica}' is not available.")
|
|
158
|
+
continue
|
|
159
|
+
|
|
160
|
+
if settings.REPLICA_READ_STRATEGY == ReplicaReadStrategy.DISTRIBUTED:
|
|
161
|
+
for _ in range(len(local_replicas)):
|
|
162
|
+
attempted_replica = random.choice(local_replicas)
|
|
163
|
+
try:
|
|
164
|
+
connections[attempted_replica].ensure_connection()
|
|
165
|
+
chosen_replica = attempted_replica
|
|
166
|
+
break
|
|
167
|
+
except OperationalError:
|
|
168
|
+
logger.exception(f"Replica '{attempted_replica}' is not available.")
|
|
169
|
+
local_replicas.remove(attempted_replica)
|
|
170
|
+
continue
|
|
171
|
+
|
|
172
|
+
if not chosen_replica:
|
|
173
|
+
if replica_prefix == "replica_":
|
|
174
|
+
logger.warning("Falling back to cross-region replicas, if any.")
|
|
175
|
+
return using_database_replica(manager, "cross_region_replica_")
|
|
176
|
+
|
|
177
|
+
logger.warning("No replicas available.")
|
|
178
|
+
return manager
|
|
179
|
+
|
|
180
|
+
return manager.db_manager(chosen_replica)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{flagsmith_common-2.0.0/src/common/core → flagsmith_common-2.1.0/src/common/core/cli}/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{flagsmith_common-2.0.0 → flagsmith_common-2.1.0}/src/common/core/management/commands/docgen.py
RENAMED
|
File without changes
|
{flagsmith_common-2.0.0 → flagsmith_common-2.1.0}/src/common/core/management/commands/start.py
RENAMED
|
File without changes
|
{flagsmith_common-2.0.0 → flagsmith_common-2.1.0}/src/common/core/management/commands/waitfordb.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{flagsmith_common-2.0.0 → flagsmith_common-2.1.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-2.0.0 → flagsmith_common-2.1.0}/src/common/features/multivariate/serializers.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{flagsmith_common-2.0.0 → flagsmith_common-2.1.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
|
{flagsmith_common-2.0.0 → flagsmith_common-2.1.0}/src/common/migrations/helpers/postgres_helpers.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
|
{flagsmith_common-2.0.0 → flagsmith_common-2.1.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
|
|
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
|