From 490e1fa70a484fffeaf1fb7d4aa010f24c495ee8 Mon Sep 17 00:00:00 2001 From: Jan-Erik Rediger Date: Tue, 18 Jul 2023 15:18:32 +0200 Subject: [PATCH] Python: Export the `shutdown` API --- CHANGELOG.md | 2 ++ glean-core/python/glean/glean.py | 11 +++++++ glean-core/python/tests/test_glean.py | 41 +++++++++++++++++++++++++++ 3 files changed, 54 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e6efef47d0..cf7f0a5389 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,8 @@ * Rust * The Ping Rate Limit type is now accessible in the Rust Language Binding ([#2528](https://github.com/mozilla/glean/pull/2528)) * `locale` now exposed through the RLB so it can be set by consumers ([2527](https://github.com/mozilla/glean/pull/2527)) +* Python + * Added the shutdown API for Python to ensure orderly shutdown and waiting for uploader processes ([#2538](https://github.com/mozilla/glean/pull/2538)) # v53.1.0 (2023-06-28) diff --git a/glean-core/python/glean/glean.py b/glean-core/python/glean/glean.py index 52f253487d..33f1329277 100644 --- a/glean-core/python/glean/glean.py +++ b/glean-core/python/glean/glean.py @@ -427,5 +427,16 @@ def handle_client_inactive(cls): """ _uniffi.glean_handle_client_inactive() + @classmethod + def shutdown(cls): + """ + Shuts down Glean in an orderly fashion. + """ + _uniffi.glean_shutdown() + + # On top of the Glean shutdown + # we also wait for the process dispatcher to finish. + ProcessDispatcher._wait_for_last_process() + __all__ = ["Glean"] diff --git a/glean-core/python/tests/test_glean.py b/glean-core/python/tests/test_glean.py index 4a91581aed..635cb1bb34 100644 --- a/glean-core/python/tests/test_glean.py +++ b/glean-core/python/tests/test_glean.py @@ -920,3 +920,44 @@ def test_max_events_overflow(tmpdir): assert "testing" == events[0]["category"] assert "event" == events[0]["name"] assert 0 == events[0]["timestamp"] + + +def test_glean_shutdown(safe_httpserver): + """ + In theory we want to test that `Glean.shutdown` here waits for Glean + and any uploader to shut down. + In practice because the process dispatcher runs using multiprocessing + this test will succeed regardless of the `Glean.shutdown` call. + """ + + Glean._reset() + + custom_ping = PingType( + name="custom", include_client_id=True, send_if_empty=False, reason_codes=[] + ) + + counter = CounterMetricType( + CommonMetricData( + category="telemetry", + name="counter_metric", + send_in_pings=["custom"], + lifetime=Lifetime.APPLICATION, + disabled=False, + dynamic_label=None, + ) + ) + + Glean._initialize_with_tempdir_for_testing( + application_id=GLEAN_APP_ID, + application_version=glean_version, + upload_enabled=True, + configuration=Configuration(server_endpoint=safe_httpserver.url), + ) + + for _ in range(10): + counter.add(1) + custom_ping.submit() + + Glean.shutdown() + wait_for_requests(safe_httpserver, n=10) + assert 10 == len(safe_httpserver.requests)