Skip to content

Commit ed3bf6d

Browse files
jpnurmiclaude
andcommitted
feat(native): offline caching
The native daemon uses the same HTTP transport, so it gets offline caching for free as long as the cache_keep option is propagated via shared memory. Also, disable http_retry in the daemon since it is a single-shot process where retry backoff makes no sense. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent c80cd09 commit ed3bf6d

File tree

6 files changed

+37
-1
lines changed

6 files changed

+37
-1
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22

33
## Unreleased
44

5+
**Features**:
6+
7+
- Add offline caching support to the new experimental `native` backend. ([#1585](https://github.com/getsentry/sentry-native/pull/1585))
8+
59
**Fixes**:
610

711
- Fix `cache_keep` to only cache envelopes when HTTP send fails, instead of unconditionally on restart. ([#1585](https://github.com/getsentry/sentry-native/pull/1585))

src/backends/native/sentry_crash_context.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,7 @@ typedef struct {
260260
int crash_reporting_mode; // sentry_crash_reporting_mode_t
261261
bool debug_enabled; // Debug logging enabled in parent process
262262
bool attach_screenshot; // Screenshot attachment enabled in parent process
263+
bool cache_keep;
263264

264265
// Platform-specific crash context
265266
#if defined(SENTRY_PLATFORM_LINUX) || defined(SENTRY_PLATFORM_ANDROID)

src/backends/native/sentry_crash_daemon.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2966,6 +2966,7 @@ sentry__crash_daemon_main(pid_t app_pid, uint64_t app_tid, HANDLE event_handle,
29662966
// Use debug logging and screenshot settings from parent process
29672967
sentry_options_set_debug(options, ipc->shmem->debug_enabled);
29682968
options->attach_screenshot = ipc->shmem->attach_screenshot;
2969+
options->cache_keep = ipc->shmem->cache_keep;
29692970

29702971
// Set custom logger that writes to file
29712972
if (log_file) {

src/backends/sentry_backend_native.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,7 @@ native_backend_startup(
176176
// Pass debug logging setting to daemon
177177
ctx->debug_enabled = options->debug;
178178
ctx->attach_screenshot = options->attach_screenshot;
179+
ctx->cache_keep = options->cache_keep;
179180

180181
// Set up event and breadcrumb paths
181182
sentry_path_t *run_path = options->run->run_path;

tests/assertions.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -559,11 +559,12 @@ def assert_failed_proxy_auth_request(stdout):
559559

560560

561561
def wait_for_file(path, timeout=10.0, poll_interval=0.1):
562+
import glob
562563
import time
563564

564565
deadline = time.time() + timeout
565566
while time.time() < deadline:
566-
if path.exists():
567+
if glob.glob(str(path)):
567568
return True
568569
time.sleep(poll_interval)
569570
return False

tests/test_integration_native.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
from .assertions import (
2020
assert_meta,
2121
assert_session,
22+
wait_for_file,
2223
)
2324
from .conditions import has_native, is_kcov, is_asan
2425

@@ -626,3 +627,30 @@ def test_crash_mode_native_with_minidump(cmake, httpserver):
626627

627628
# Should have debug_meta
628629
assert "debug_meta" in event
630+
631+
632+
@pytest.mark.parametrize("cache_keep", [True, False])
633+
def test_native_cache_keep(cmake, cache_keep):
634+
tmp_path = cmake(["sentry_example"], {"SENTRY_BACKEND": "native"})
635+
db_dir = tmp_path / ".sentry-native"
636+
cache_dir = db_dir / "cache"
637+
unreachable_dsn = "http://uiaeosnrtdy@127.0.0.1:19999/123456"
638+
env = dict(os.environ, SENTRY_DSN=unreachable_dsn)
639+
640+
# crash -> daemon sends via HTTP -> unreachable -> cache
641+
run_crash(
642+
tmp_path,
643+
"sentry_example",
644+
["log", "stdout", "crash"] + (["cache-keep"] if cache_keep else []),
645+
env=env,
646+
)
647+
648+
if cache_keep:
649+
assert wait_for_file(cache_dir / "*.envelope")
650+
assert len(list(cache_dir.glob("*.envelope"))) == 1
651+
else:
652+
# Best-effort wait for crash processing to finish. 2s is not
653+
# guaranteed to be enough, but we cannot poll for the non-existence
654+
# of a file.
655+
time.sleep(2)
656+
assert len(list(cache_dir.glob("*.envelope"))) == 0

0 commit comments

Comments
 (0)