Skip to content

Commit b319fd4

Browse files
fix: Unstable PROMETHEUS_MULTIPROC_DIR (#116)
* fix: Unstable `PROMETHEUS_MULTIPROC_DIR` * avoid circular imports, fix tests * remove `PROMETHEUS_MULTIPROC_DIR_KEEP` * Remove unnecessary `Env()` instantiation --------- Co-authored-by: Matthew Elwell <[email protected]>
1 parent 00a973a commit b319fd4

File tree

4 files changed

+20
-70
lines changed

4 files changed

+20
-70
lines changed

src/common/core/constants.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
DEFAULT_PROMETHEUS_MULTIPROC_DIR = "/tmp/flagsmith-prometheus"

src/common/core/main.py

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
import contextlib
22
import logging
33
import os
4+
import shutil
45
import sys
56
import typing
67

78
from django.core.management import (
89
execute_from_command_line as django_execute_from_command_line,
910
)
10-
from environs import Env
1111

1212
from common.core.cli import healthcheck
13-
from common.core.utils import TemporaryDirectory
13+
from common.core.constants import DEFAULT_PROMETHEUS_MULTIPROC_DIR
1414

1515
logger = logging.getLogger(__name__)
1616

@@ -31,7 +31,6 @@ def ensure_cli_env() -> typing.Generator[None, None, None]:
3131
main()
3232
```
3333
"""
34-
env = Env()
3534
ctx = contextlib.ExitStack()
3635

3736
# TODO @khvn26 Move logging setup to here
@@ -45,16 +44,16 @@ def ensure_cli_env() -> typing.Generator[None, None, None]:
4544
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "settings.dev")
4645

4746
# Set up Prometheus' multiprocess mode
48-
if not env.str("PROMETHEUS_MULTIPROC_DIR", ""):
49-
delete = not env.bool("PROMETHEUS_MULTIPROC_DIR_KEEP", False)
50-
prometheus_multiproc_dir_name = ctx.enter_context(
51-
TemporaryDirectory(delete=delete)
52-
)
53-
logger.info(
54-
"Created %s for Prometheus multi-process mode",
55-
prometheus_multiproc_dir_name,
56-
)
57-
os.environ["PROMETHEUS_MULTIPROC_DIR"] = prometheus_multiproc_dir_name
47+
prometheus_multiproc_dir_name = os.environ.setdefault(
48+
"PROMETHEUS_MULTIPROC_DIR",
49+
DEFAULT_PROMETHEUS_MULTIPROC_DIR,
50+
)
51+
shutil.rmtree(prometheus_multiproc_dir_name, ignore_errors=True)
52+
os.makedirs(prometheus_multiproc_dir_name, exist_ok=True)
53+
logger.info(
54+
"Re-created %s for Prometheus multi-process mode",
55+
prometheus_multiproc_dir_name,
56+
)
5857

5958
if "docgen" in sys.argv:
6059
os.environ["DOCGEN_MODE"] = "true"

src/common/core/utils.py

Lines changed: 0 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22
import logging
33
import pathlib
44
import random
5-
import sys
6-
import tempfile
75
from functools import lru_cache
86
from itertools import cycle
97
from typing import (
@@ -200,40 +198,3 @@ def using_database_replica(
200198
return manager
201199

202200
return manager.db_manager(chosen_replica)
203-
204-
205-
if sys.version_info >= (3, 12):
206-
# Already has the desired behavior; re-export for uniform imports.
207-
TemporaryDirectory = tempfile.TemporaryDirectory
208-
else:
209-
import contextlib
210-
from typing import ContextManager, Generator
211-
212-
def TemporaryDirectory(
213-
suffix: str | None = None,
214-
prefix: str | None = None,
215-
dir: str | None = None,
216-
*,
217-
delete: bool = True,
218-
) -> ContextManager[str]:
219-
"""
220-
Create a temporary directory with optional cleanup control.
221-
222-
This wrapper exists because Python 3.12 changed TemporaryDirectory's behavior
223-
by adding a 'delete' parameter, which doesn't exist in Python 3.11. This
224-
function provides a consistent API across both versions.
225-
226-
When delete=True, uses the stdlib's TemporaryDirectory (auto-cleanup).
227-
When delete=False, creates a directory with mkdtemp that persists after
228-
the context manager exits, matching Python 3.12's delete=False behavior.
229-
230-
See https://docs.python.org/3.12/library/tempfile.html#tempfile.TemporaryDirectory for usage details.
231-
"""
232-
if delete:
233-
return tempfile.TemporaryDirectory(suffix, prefix, dir)
234-
235-
@contextlib.contextmanager
236-
def _tmpdir() -> Generator[str, None, None]:
237-
yield tempfile.mkdtemp(suffix, prefix, dir)
238-
239-
return _tmpdir()

tests/integration/core/test_main.py

Lines changed: 7 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
import os
21
import subprocess
3-
from pathlib import Path
42

53
import django
64
import pytest
@@ -111,32 +109,23 @@ def test_main__healthcheck_http__server_invalid_response__runs_expected(
111109
main(argv)
112110

113111

114-
def test_main__prometheus_multiproc_remove_dir_on_exit_default__expected(
112+
def test_main__prometheus_multiproc_remove_dir_on_start_default__expected(
115113
monkeypatch: pytest.MonkeyPatch,
114+
fs: FakeFilesystem,
116115
) -> None:
117116
# Given
118117
monkeypatch.delenv("PROMETHEUS_MULTIPROC_DIR_KEEP", raising=False)
119118

120-
# When
121-
main(["flagsmith"])
122-
123-
# Then
124-
assert not Path(os.environ["PROMETHEUS_MULTIPROC_DIR"]).exists()
125-
126-
127-
def test_main__prometheus_multiproc_remove_dir_on_exit_true__expected(
128-
monkeypatch: pytest.MonkeyPatch,
129-
fs: FakeFilesystem,
130-
) -> None:
131-
# Given
132-
monkeypatch.delenv("PROMETHEUS_MULTIPROC_DIR")
133-
monkeypatch.setenv("PROMETHEUS_MULTIPROC_DIR_KEEP", "true")
119+
fs.create_file(
120+
"/tmp/flagsmith-prometheus/some_metric_file.db",
121+
create_missing_dirs=True,
122+
)
134123

135124
# When
136125
main(["flagsmith"])
137126

138127
# Then
139-
assert Path(os.environ["PROMETHEUS_MULTIPROC_DIR"]).exists()
128+
assert not fs.exists("/tmp/flagsmith-prometheus/some_metric_file.db")
140129

141130

142131
def test_main__no_django_configured__expected_0(

0 commit comments

Comments
 (0)