Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
307 commits
Select commit Hold shift + click to select a range
04f1c03
Fold the online catch-up delivery into updateScheduledTasks
abelonogov-ld Sep 22, 2026
7385975
Merge branch 'andrey/event-durability-tier1-buffer' into andrey/event…
abelonogov-ld Sep 22, 2026
288680a
Merge branch 'andrey/event-durability-tier2-bounded-flush' into andre…
abelonogov-ld Sep 22, 2026
2746950
Drop unserializable events and summaries on the persistence path too
abelonogov-ld Sep 22, 2026
29991ab
Merge branch 'main' into andrey/event-durability-tier1-buffer
abelonogov-ld Sep 22, 2026
f278820
Merge branch 'andrey/event-durability-tier1-buffer' into andrey/event…
abelonogov-ld Sep 22, 2026
6a73c56
Merge branch 'andrey/event-durability-tier2-bounded-flush' into andre…
abelonogov-ld Sep 22, 2026
9d69347
Post diagnostic events off the analytics delivery thread
abelonogov-ld Sep 22, 2026
c6386f7
Merge branch 'andrey/event-durability-tier1-buffer' into andrey/event…
abelonogov-ld Sep 22, 2026
c71c976
Merge branch 'andrey/event-durability-tier2-bounded-flush' into andre…
abelonogov-ld Sep 22, 2026
303580c
Rename eventSender to diagnosticEventSender
abelonogov-ld Sep 22, 2026
46cca56
Use volatile for the flags that never do a compound update
abelonogov-ld Sep 22, 2026
f36aee4
Merge branch 'andrey/event-durability-tier1-buffer' into andrey/event…
abelonogov-ld Sep 22, 2026
83c43a1
Merge branch 'andrey/event-durability-tier2-bounded-flush' into andre…
abelonogov-ld Sep 22, 2026
c949ab4
Make the close checks either locked, deleted, or documented
abelonogov-ld Sep 22, 2026
23bba70
Merge branch 'andrey/event-durability-tier1-buffer' into andrey/event…
abelonogov-ld Sep 22, 2026
08fe09d
Merge branch 'andrey/event-durability-tier2-bounded-flush' into andre…
abelonogov-ld Sep 22, 2026
433cf2e
Bound how many contexts are summarized at once
abelonogov-ld Sep 22, 2026
a408e75
Merge branch 'andrey/event-durability-tier1-buffer' into andrey/event…
abelonogov-ld Sep 22, 2026
aeaa74b
Merge branch 'andrey/event-durability-tier2-bounded-flush' into andre…
abelonogov-ld Sep 22, 2026
8f7762c
Reset the counted contexts wherever the counters are reset
abelonogov-ld Sep 22, 2026
113ee34
Merge branch 'andrey/event-durability-tier1-buffer' into andrey/event…
abelonogov-ld Sep 22, 2026
1b027b1
Merge branch 'andrey/event-durability-tier2-bounded-flush' into andre…
abelonogov-ld Sep 22, 2026
b35f4cd
Record an evaluation's counter and events under one lock
abelonogov-ld Sep 22, 2026
70babb2
Merge branch 'andrey/event-durability-tier1-buffer' into andrey/event…
abelonogov-ld Sep 22, 2026
b093a92
Merge branch 'andrey/event-durability-tier2-bounded-flush' into andre…
abelonogov-ld Sep 22, 2026
115a312
Build the diagnostic period on the thread that posts it
abelonogov-ld Sep 22, 2026
ff5aeec
Merge branch 'andrey/event-durability-tier1-buffer' into andrey/event…
abelonogov-ld Sep 22, 2026
a14aaf7
Merge branch 'andrey/event-durability-tier2-bounded-flush' into andre…
abelonogov-ld Sep 22, 2026
0df02b8
Treat a capacity of nought as one, in both places that bound by it
abelonogov-ld Sep 22, 2026
b414476
Report the capacity the SDK will use, and stop the race test overrunn…
abelonogov-ld Sep 22, 2026
105c870
Merge branch 'andrey/event-durability-tier1-buffer' into andrey/event…
abelonogov-ld Sep 22, 2026
73eaf53
Merge branch 'andrey/event-durability-tier2-bounded-flush' into andre…
abelonogov-ld Sep 22, 2026
67690b3
Clamp the capacity where it is set, not where it is used
abelonogov-ld Sep 22, 2026
bdfd13a
Merge branch 'andrey/event-durability-tier1-buffer' into andrey/event…
abelonogov-ld Sep 22, 2026
58492bb
Merge branch 'andrey/event-durability-tier2-bounded-flush' into andre…
abelonogov-ld Sep 22, 2026
38337ab
Make the diagnostics tests real, and cover shutdown and the flush race
abelonogov-ld Sep 22, 2026
6290c38
Merge branch 'andrey/event-durability-tier1-buffer' into andrey/event…
abelonogov-ld Sep 22, 2026
3fb426c
Merge branch 'andrey/event-durability-tier2-bounded-flush' into andre…
abelonogov-ld Sep 22, 2026
af84244
Keep context-limit test payloads small enough for the test server
abelonogov-ld Sep 23, 2026
ee78359
Merge branch 'andrey/event-durability-tier1-buffer' into andrey/event…
abelonogov-ld Sep 23, 2026
2ae461c
Merge branch 'andrey/event-durability-tier2-bounded-flush' into andre…
abelonogov-ld Sep 23, 2026
f3a0f75
Document that close() discards events held while offline
abelonogov-ld Sep 23, 2026
c629046
Merge branch 'andrey/event-durability-tier1-buffer' into andrey/event…
abelonogov-ld Sep 23, 2026
5421ffd
Merge branch 'andrey/event-durability-tier2-bounded-flush' into andre…
abelonogov-ld Sep 23, 2026
f1263bc
Keep the flush interval running while offline instead of delivering o…
abelonogov-ld Sep 23, 2026
2237489
Merge branch 'andrey/event-durability-tier1-buffer' into andrey/event…
abelonogov-ld Sep 23, 2026
7271754
Merge branch 'andrey/event-durability-tier2-bounded-flush' into andre…
abelonogov-ld Sep 23, 2026
30ae37a
Fix the instrumented benchmark's OutboundEventBuffer call for the cur…
abelonogov-ld Sep 23, 2026
394ae90
Count events a commit is staging against capacity
abelonogov-ld Sep 23, 2026
b42f022
Keep tier-3 event persistence disk work off the caller's thread
abelonogov-ld Sep 23, 2026
9c8c889
Make stopping scheduled event tasks independent of the closed check
abelonogov-ld Sep 23, 2026
df9e409
Merge branch 'andrey/event-durability-tier1-buffer' into andrey/event…
abelonogov-ld Sep 23, 2026
6b9bfb1
Merge branch 'andrey/event-durability-tier2-bounded-flush' into andre…
abelonogov-ld Sep 23, 2026
e113694
Report a failed flushAndWait from a closed client
abelonogov-ld Sep 23, 2026
4ea6deb
Merge branch 'andrey/event-durability-tier2-bounded-flush' into andre…
abelonogov-ld Sep 23, 2026
4db9fa7
Restore split-evaluation coverage on tier 3 at the commit boundary
abelonogov-ld Sep 23, 2026
cdfa78d
Keep the event store off the filesystem when persistence is disabled
abelonogov-ld Sep 23, 2026
d27473a
Isolate recording exceptions and reset context limit warning per run
abelonogov-ld Sep 23, 2026
15d3ffa
Tighten recording error handling and the per-run context warning
abelonogov-ld Sep 23, 2026
4ac8572
Merge branch 'andrey/event-durability-tier1-buffer' into andrey/event…
abelonogov-ld Sep 23, 2026
b744e54
Merge tier 2 (tier-1 recording follow-ups) into tier 3
abelonogov-ld Sep 23, 2026
48c6378
Recover the interrupted log before this run first appends to it
abelonogov-ld Sep 23, 2026
9740da3
check persisting
abelonogov-ld Sep 25, 2026
97a17f3
Close the event log if writing its header fails
abelonogov-ld Sep 27, 2026
7ecc1c4
Describe the diagnostic recording interval once
abelonogov-ld Sep 27, 2026
11b788e
Count events on their way into the store exactly once against capacity
abelonogov-ld Sep 27, 2026
741d83f
Summarize per context without Java 8 library calls Android lacks belo…
abelonogov-ld Sep 27, 2026
f432d58
Commit on the store's thread and schedule the delivery retry
abelonogov-ld Sep 28, 2026
68d3dbf
Take less work onto the evaluating thread
abelonogov-ld Sep 28, 2026
e35867e
Group concurrent IMMEDIATE commit points into one commit
abelonogov-ld Sep 28, 2026
92e47dd
Queue no commit at a commit point where there is no disk
abelonogov-ld Sep 28, 2026
8cb6842
Answer isPersisting without the staging lock
abelonogov-ld Sep 28, 2026
11e8a4e
Wait for the commit thread, not the events thread, before counting a …
abelonogov-ld Sep 28, 2026
e2437b4
Update java-sdk-internal to 1.12.1
abelonogov-ld Sep 28, 2026
7fe25ed
Merge branch 'andrey/event-durability-tier1-buffer' into andrey/event…
abelonogov-ld Sep 28, 2026
23ff461
Merge branch 'andrey/event-durability-tier2-bounded-flush' into andre…
abelonogov-ld Sep 28, 2026
0290a36
comment fix
abelonogov-ld Sep 29, 2026
b5c64a0
Merge branch 'main' into andrey/event-durability-tier1-buffer
abelonogov-ld Sep 29, 2026
6f1ae80
Flush through a future, shared by the callers who asked at once
abelonogov-ld Oct 2, 2026
3ab2ffc
Merge branch 'andrey/event-durability-tier1-buffer' into andrey/event…
abelonogov-ld Oct 2, 2026
2979a73
Merge branch 'andrey/event-durability-tier2-bounded-flush' into andre…
abelonogov-ld Oct 2, 2026
90f4eed
change to 500 ms
abelonogov-ld Oct 6, 2026
14b9e47
Tell a flush caller about events an earlier delivery took and lost
abelonogov-ld Oct 6, 2026
6de55d5
Keep flushAndWait bounded at Long.MIN_VALUE and boolean on a cancelle…
abelonogov-ld Oct 6, 2026
0421534
fix
abelonogov-ld Oct 6, 2026
51bae97
Pin flushAndWait's outcome for refused posts, abandoned waits and par…
abelonogov-ld Oct 6, 2026
30a5008
Move the crash flush into the SDK as EventFlushingCrashHandler
abelonogov-ld Oct 6, 2026
f229dde
Rename EventFlushingCrashHandler to LDCrashHandler
abelonogov-ld Oct 6, 2026
b8fd94c
Pin the 503 outcomes Todd proposed, say refused events are not kept, …
abelonogov-ld Oct 7, 2026
49c3bdf
Merge branch 'andrey/event-durability-tier2-bounded-flush' into andre…
abelonogov-ld Oct 7, 2026
7457a26
Say how long a failing delivery takes, so a shorter flushAndWait budg…
abelonogov-ld Oct 7, 2026
c65be26
Pin that a refused batch is posted only by each delivery and its one …
abelonogov-ld Oct 7, 2026
61ba012
Merge branch 'andrey/event-durability-tier2-bounded-flush' into andre…
abelonogov-ld Oct 7, 2026
d35b345
Sample an event once, as it is recorded, not again as it is staged
abelonogov-ld Oct 7, 2026
78ef0b8
Deliver every event left behind when persistence fails, and report ev…
abelonogov-ld Oct 7, 2026
d3d7151
Keep stored events whose read fails instead of deleting them
abelonogov-ld Oct 7, 2026
ec6e121
Split the log format and this process's open log out of EventStore
abelonogov-ld Oct 10, 2026
caefa58
Keep the batch paths off the disk, and out of ioLock, when persistenc…
abelonogov-ld Oct 11, 2026
9513935
Tell the delivery that closed the batch about a loss, not whichever a…
abelonogov-ld Oct 11, 2026
705197e
Merge remote-tracking branch 'origin/main' into andrey/event-durabili…
abelonogov-ld Oct 11, 2026
42aa53c
Take the frames a failed write left back off the log, so they are not…
abelonogov-ld Oct 12, 2026
1fc2081
Rename OpenEventLog to DiskEventLog, so it reads apart from diagnosti…
abelonogov-ld Oct 12, 2026
2464bdb
Remove the whole-run encoder, which nothing but two tests still called
abelonogov-ld Oct 12, 2026
c394ee1
Commit first at close, and never wait past the budget on the caller's…
abelonogov-ld Oct 12, 2026
b4dd983
Group the DirectEventProcessor fields by the lock that guards them
abelonogov-ld Oct 12, 2026
6fb00b4
Keep counting events against capacity while they are on their way out…
abelonogov-ld Oct 12, 2026
cc1b040
Keep the closed-batch count equal to the batches it counts
abelonogov-ld Oct 12, 2026
87e2b21
Stop counting a batch against capacity while its request is out
abelonogov-ld Oct 12, 2026
e184d34
unit tests for disabled
abelonogov-ld Oct 12, 2026
92af3fc
Give the event directory a class of its own
abelonogov-ld Oct 12, 2026
335e7cb
Stop re-sending a delivered batch whose file will not delete
abelonogov-ld Oct 12, 2026
d94c586
Raise the default event capacity to 2000
abelonogov-ld Oct 12, 2026
13727c1
Commit before every flush's delivery, not only flush()
abelonogov-ld Oct 12, 2026
58decdb
Write on flush at DEFERRED too
abelonogov-ld Oct 12, 2026
0a1e8ed
Leave scheduling writes to the event processor, and count a batch's e…
abelonogov-ld Oct 12, 2026
fab94f2
combobox
abelonogov-ld Oct 13, 2026
0c05225
Report a stored batch this version cannot read as lost
abelonogov-ld Oct 13, 2026
3587b23
Report an unreadable batch as lost, and return every batch closeBatch…
abelonogov-ld Oct 13, 2026
5c05668
Do not take a payload id ending in zero-led digits for a count
abelonogov-ld Oct 13, 2026
7ce165f
Serve the concurrent recording test from MockWebServer
Oct 20, 2026
b117477
Bound stored events by bytes and by age
abelonogov-ld Oct 20, 2026
6cf1263
Checksum every frame of the event log
abelonogov-ld Oct 21, 2026
3569b98
Keep the checksummed log format at version 1
abelonogov-ld Oct 21, 2026
42fc412
experimental
abelonogov-ld Oct 21, 2026
a8ccb4e
Name each event log by a UUID and recover every log no live process h…
abelonogov-ld Oct 21, 2026
9c84d70
Stop asking the platform for the process name
abelonogov-ld Oct 21, 2026
e077bec
Name an event log pending- rather than open-
abelonogov-ld Oct 21, 2026
82f53d8
Log events from a previous run as prepared, not recovered
abelonogov-ld Oct 21, 2026
1d501fd
Rename recoverInterruptedLog to preparePayloadsFromInterruptedLogs
abelonogov-ld Oct 21, 2026
e431fba
Send a batch's events no more than once when a failed write stays on …
abelonogov-ld Oct 21, 2026
0b01306
Warn when events from a previous run cannot be moved for delivery
abelonogov-ld Oct 21, 2026
2bed8f2
Admit a recorded event under one acquisition of the store's lock
abelonogov-ld Oct 21, 2026
83e93af
Keep every batch within 2 MiB, so no request is too large to accept
abelonogov-ld Oct 21, 2026
08f686c
Hold a batch being delivered twice at most, rather than four times
abelonogov-ld Oct 21, 2026
0c87a6d
Tell the next flush about a batch lost where nobody was waiting
abelonogov-ld Oct 21, 2026
257da89
Say when a read that failed is tried again
abelonogov-ld Oct 21, 2026
e5421f0
Leave a batch out of the count only while it is still counted
abelonogov-ld Oct 21, 2026
ae7cffb
Call the file openForAppending opens a file, not a log
abelonogov-ld Oct 21, 2026
94effc2
Mark the create() overloads that take a directory as for tests
abelonogov-ld Oct 21, 2026
2862ee6
Keep one create() that takes a directory
abelonogov-ld Oct 21, 2026
7e345ac
Name the flag IMMEDIATE persistence sets
abelonogov-ld Oct 21, 2026
fe0d7b9
Rename cutBack to truncate
abelonogov-ld Oct 21, 2026
22788c1
Rename deleteQuietly to tryDelete
abelonogov-ld Oct 21, 2026
f070a73
Say remove() removes a batch, rather than forgets it
abelonogov-ld Oct 21, 2026
9588c49
Spell out the log's magic bytes rather than encode them
abelonogov-ld Oct 21, 2026
7e154cd
Assemble a batch's payload in the array its file was read into
abelonogov-ld Oct 21, 2026
a1472a7
Make Frames an Iterator that returns the next frame
abelonogov-ld Oct 21, 2026
74e028a
Move hexDigest into LDUtil beside the other hashing helpers
abelonogov-ld Oct 21, 2026
fe19306
Name batches ready-<payloadId>.<count>, read by position
abelonogov-ld Oct 22, 2026
53338d4
test-app: add a button recording events too large for one batch
abelonogov-ld Oct 22, 2026
45e42c2
Test that a flush of more than a batch sends no request over the batc…
abelonogov-ld Oct 22, 2026
fceb15e
Fix inspection warnings in DirectEventProcessor
abelonogov-ld Oct 22, 2026
e1ead03
Fix inspection warnings in DiskEventLog
abelonogov-ld Oct 22, 2026
19e19c0
Fix inspection warnings in EventDirectory
abelonogov-ld Oct 22, 2026
60f2a09
Fix inspection warnings in EventStore
abelonogov-ld Oct 22, 2026
1f5631c
Merge remote-tracking branch 'origin/main' into andrey/event-durabili…
abelonogov-ld Oct 22, 2026
edaf0a2
Merge branch 'andrey/event-durability-tier1-buffer' into andrey/event…
abelonogov-ld Oct 22, 2026
6a0e2eb
Merge branch 'andrey/event-durability-tier2-bounded-flush' into andre…
abelonogov-ld Oct 22, 2026
7d2b222
Mark the tier 2 public methods as experimental
abelonogov-ld Oct 22, 2026
0c48b91
Merge branch 'andrey/event-durability-tier2-bounded-flush' into andre…
abelonogov-ld Oct 22, 2026
f02faff
Hold the commit thread so a queued commit cannot cover what a flush w…
abelonogov-ld Oct 22, 2026
333f272
fix: Bound flushAndWait's timeout across its commit (ATR3-004)
abelonogov-ld Oct 22, 2026
14d8ef2
docs: Say where flushAndWait writes, now that its timeout bounds it
abelonogov-ld Oct 22, 2026
9f8ad67
fix: Keep a log whose close failed open, so its count stays its own (…
abelonogov-ld Oct 22, 2026
be46624
fix: Close no batch behind one that is blocked (ATR3-006, part 1)
abelonogov-ld Oct 22, 2026
3f2c48d
fix: Bound summaries by bytes where events stay off the disk (ATR3-00…
abelonogov-ld Oct 22, 2026
ced788f
fix: Leave summaries out of the event count (ATR3-006, part 3)
abelonogov-ld Oct 22, 2026
ad74c09
fix: Keep expiry away from batches any live store or process is sendi…
abelonogov-ld Oct 22, 2026
9979c77
fix: Never recreate a batch expiry finds gone (ATR3-007)
abelonogov-ld Oct 22, 2026
649dcc3
fix: Report a flush as failed when the stored events cannot be listed…
abelonogov-ld Oct 22, 2026
3909f33
fix: Report a flush as failed while the event log will not close (ATR…
abelonogov-ld Oct 22, 2026
85a6c7d
fix: Report the events a damaged batch could not send (ATR3-032)
abelonogov-ld Oct 22, 2026
e67ea4a
fix: Read the logs a previous run left without holding the store's I/…
abelonogov-ld Oct 22, 2026
3f0d8ac
docs: Stop calling the commit threshold a bound on track (ATR3-034)
abelonogov-ld Oct 22, 2026
ee933cb
fix: Start the test app's replacement client in the offline switch's …
abelonogov-ld Oct 22, 2026
4d6935c
fix: back off failed event deliveries per RETRY instead of disabling …
abelonogov-ld Oct 22, 2026
0ff1a81
fix: drop a batch after two 400s in a row so it cannot block the rest…
abelonogov-ld Oct 22, 2026
6e4a43c
test: pin that an unencodable summary is dropped and reported (ATR3-009)
abelonogov-ld Oct 22, 2026
ec16460
fix: encode nothing for an offline flush or close where events do not…
abelonogov-ld Oct 22, 2026
a4b6dec
fix: tell every overlapping flush of a loss in its window (ATR3-016)
abelonogov-ld Oct 22, 2026
108327e
docs: describe one delivery thread per processor, and overlap across …
abelonogov-ld Oct 23, 2026
57962ff
test: record whole request bodies in the test HTTP server
abelonogov-ld Oct 23, 2026
69189a7
test: listen on 127.0.0.1 so the test server never shares a port
abelonogov-ld Oct 23, 2026
0a0681c
test: set retry answers up front where a switch could race the retry
abelonogov-ld Oct 23, 2026
9300b37
test: wait for the store to ask where it lives instead of flushing
abelonogov-ld Oct 23, 2026
80214dc
test: port the iOS event store specs Android lacked
abelonogov-ld Oct 23, 2026
543891c
fix: remove a first log a failed write left frames in and could not t…
abelonogov-ld Oct 23, 2026
be7cc12
test: port the iOS event processor specs Android lacked
abelonogov-ld Oct 23, 2026
2405b45
fix: tell a loss only to the flush whose delivery passed it, as iOS does
abelonogov-ld Oct 23, 2026
8298fcf
refactor: put each frame's checksum after its payload, as iOS does
abelonogov-ld Oct 23, 2026
85edf61
docs: say why reading a batch goes past the size the file reported
abelonogov-ld Oct 23, 2026
355f068
refactor: size a stored file from its open descriptor rather than gro…
abelonogov-ld Oct 23, 2026
70a130d
fix: leave a stale file expiry cannot read rather than discard it unc…
abelonogov-ld Oct 23, 2026
33cec21
fix: open every new event log under a fresh name
abelonogov-ld Oct 23, 2026
684fe8f
fix: keep a batch's counted size where length() cannot look
abelonogov-ld Oct 23, 2026
4a2d00a
test-app: add a Benchmark button running the event persistence benchmark
abelonogov-ld Oct 26, 2026
220c04f
test-app: move the Benchmark button under the status text
abelonogov-ld Oct 27, 2026
c351551
fix: requeue a retry the backoff stopped, so flushes behind it reach …
abelonogov-ld Oct 27, 2026
1dcb68c
fix: commit on the periodic flush while offline
abelonogov-ld Oct 27, 2026
4bb740e
fix: let the final delivery at close post through the backoff
abelonogov-ld Oct 27, 2026
7b57328
fix: Update java-sdk-internal to 1.12.2 to report all-private attribu…
abelonogov-ld Oct 27, 2026
64292a4
fix: count the loss when a previous run's event log is damaged
abelonogov-ld Oct 27, 2026
5db0ad1
Add a Post 20 MB button posting one oversized payload past the SDK in…
abelonogov-ld Oct 27, 2026
7919710
fix(events): drop a batch after two 413, 415 or 422 refusals, as for 400
abelonogov-ld Oct 27, 2026
ee4052f
Name every file in the event directory in EventDirectory
abelonogov-ld Oct 27, 2026
7b92ddc
Mark sections the way the rest of the Java code does
abelonogov-ld Oct 27, 2026
a84576e
fix: refuse to read a stored file larger than this version writes
abelonogov-ld Oct 27, 2026
529f0e4
feat: version batch names, so a later name format is never misread
abelonogov-ld Oct 27, 2026
72458c4
fix: count a batch read to count it by the bytes that were read
abelonogov-ld Oct 27, 2026
75e24c5
docs: keep EventDirectory's class comment to what it does itself
abelonogov-ld Oct 27, 2026
a3a2c7c
fix: leave a batch another version named to expiry, uncounted and unsent
abelonogov-ld Oct 27, 2026
f633faa
Merge branch 'andrey/event-durability-tier1-buffer' into andrey/event…
abelonogov-ld Oct 27, 2026
bc9d725
Merge branch 'andrey/event-durability-tier2-bounded-flush' into andre…
abelonogov-ld Oct 27, 2026
5df5e39
test: pace the lister so closes are not starved of the store's lock
abelonogov-ld Oct 27, 2026
cf685ec
feat: tell the event processor when a flag request starts and settles
abelonogov-ld Oct 28, 2026
33af63a
feat: give flag requests the network ahead of a backlog of events
abelonogov-ld Oct 28, 2026
a76b94d
feat: share the byte capacity equally across the configured environments
abelonogov-ld Oct 28, 2026
b208fb1
fix: count the wait for a flag request from when it started, so the l…
abelonogov-ld Oct 28, 2026
cdb2ce6
fix: report the flag request stopped when the client shuts down befor…
abelonogov-ld Oct 28, 2026
2eb92f6
test: going offline stops a paced delivery and the retry of a failed …
abelonogov-ld Oct 28, 2026
51aa35e
PERSISTANCE gates
abelonogov-ld Oct 28, 2026
f7a6a85
refactor: give way to flag values by time alone, without tracking fla…
abelonogov-ld Oct 28, 2026
46ea741
refactor: move diagnostic events out of DirectEventProcessor into Dia…
abelonogov-ld Oct 28, 2026
614b24d
refactor: move recording and commits out of DirectEventProcessor into…
abelonogov-ld Oct 28, 2026
85906f2
Move delivery queueing and pacing out of DirectEventProcessor
abelonogov-ld Oct 28, 2026
a16e4b6
Rename DeliveryScheduler to EventDeliveryScheduler
abelonogov-ld Oct 28, 2026
6bc50d1
Rename DeliveryRun to EventDeliveryRun
abelonogov-ld Oct 28, 2026
72508f5
Show the expected HTTP 413 on the Post 20 MB button
abelonogov-ld Oct 28, 2026
76f5197
Hold the periodic flush's deliveries until the launch gate opens
abelonogov-ld Oct 28, 2026
0afebbe
Post through the backoff from flushAndWait and LDCrashHandler
abelonogov-ld Oct 29, 2026
1a582c1
Rename flushAsLastChance to flushBypassingBackoff
abelonogov-ld Oct 29, 2026
9eae319
Keep one unencodable event from losing the whole commit
abelonogov-ld Oct 29, 2026
f75c359
fix: flushes waiting on the retry a second later hold no thread
abelonogov-ld Oct 30, 2026
0117df2
fix: a post that gets no response leaves the run of payload refusals …
abelonogov-ld Oct 30, 2026
283b128
docs: flushAndWait no longer says every flush retries refused events
abelonogov-ld Oct 30, 2026
061b8c6
fix: bound full events by bytes where persistence is off
abelonogov-ld Oct 30, 2026
657071c
fix: count the events of an open log found gone while it was held as …
abelonogov-ld Oct 30, 2026
c51feff
fix: count an uncounted batch this version cannot read as lost rather…
abelonogov-ld Oct 30, 2026
3f19a4f
fix: count an uncounted batch damaged from its first frame as one eve…
abelonogov-ld Oct 30, 2026
2152b71
fix: pass by a stored batch whose read fails, and drop it after three…
abelonogov-ld Oct 30, 2026
172126c
fix: give each event directory its own BatchLocks monitor
abelonogov-ld Oct 30, 2026
ff22572
fix: split a summary too large for a log frame rather than dropping it
abelonogov-ld Oct 30, 2026
b600d73
Stop DEFERRED track and identify from scheduling a commit each (ATR3-…
abelonogov-ld Oct 30, 2026
8035b77
Drop the per-track commit from two EventCommitter comments (ATR3-010)
abelonogov-ld Oct 30, 2026
b6a921d
Say where DEFERRED events are written on backgrounding
abelonogov-ld Oct 30, 2026
ed64f5d
A failed post through the backoff leaves the wait as it was
abelonogov-ld Oct 30, 2026
c768cb6
Space the read failures that drop a batch a flush interval apart
abelonogov-ld Oct 30, 2026
d9e4be5
Stop splitting a summary that is mostly context
abelonogov-ld Oct 30, 2026
57d3ebb
Pack an oversized summary's flags into parts that fit beside the context
abelonogov-ld Oct 30, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
.gradle
/local.properties
local.properties
.DS_Store
build
/captures
Expand Down
2 changes: 0 additions & 2 deletions example/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@ import java.util.Properties

plugins {
id("com.android.application")
// make sure this line comes *after* you apply the Android plugin
id("com.getkeepsafe.dexcount")
}

// local.properties is not checked in, so it is where machine-specific settings such as your mobile
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,6 @@

import java.util.Date;
import java.util.Locale;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicInteger;

import timber.log.Timber;
Expand All @@ -45,6 +41,9 @@ public class MainActivity extends AppCompatActivity {

private static final String DEFAULT_USER_KEY = "user key";

/** How long startup blocks waiting for the first flags to arrive. */
private static final int INIT_WAIT_SECONDS = 10;

private LDClient ldClient;
private LDStatusListener ldStatusListener;
private LDAllFlagsListener allFlagsListener;
Expand Down Expand Up @@ -142,15 +141,12 @@ public void onCreate(Bundle savedInstanceState) {
.set("email", "fake@example.com")
.build();

Future<LDClient> initFuture = LDClient.init(this.getApplication(), ldConfig, context);
try {
ldClient = initFuture.get(10, TimeUnit.SECONDS);
updateStatusString(ldClient.getConnectionInformation());
ldClient.registerStatusListener(ldStatusListener);
ldClient.registerAllFlagsListener(allFlagsListener);
} catch (InterruptedException | ExecutionException | TimeoutException e) {
Timber.e(e, "Exception when awaiting LaunchDarkly Client initialization");
}
// Returns the client either way: if the flags have not arrived within the wait, it is usable
// with whatever it has cached.
ldClient = LDClient.init(this.getApplication(), ldConfig, context, INIT_WAIT_SECONDS);
updateStatusString(ldClient.getConnectionInformation());
ldClient.registerStatusListener(ldStatusListener);
ldClient.registerAllFlagsListener(allFlagsListener);
}

private void setupListeners() {
Expand Down
28 changes: 26 additions & 2 deletions launchdarkly-android-client-sdk/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,30 @@ android {
// that the app's state is completely cleared between tests.
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
testInstrumentationRunnerArguments["clearPackageData"] = "true"
if (System.getenv("LD_EVENT_BENCH") == "1") {
// The device benchmark writes one results file for the class. Orchestrator's
// "pm clear" between methods would wipe it, and the runner does not inherit the
// shell environment, so the gate is passed as an instrumentation argument.
testInstrumentationRunnerArguments["clearPackageData"] = "false"
testInstrumentationRunnerArguments["LD_EVENT_BENCH"] = "1"
}
}

testOptions {
execution = "ANDROIDX_TEST_ORCHESTRATOR"
// EventPersistenceBenchmark on a device keeps one process for the class so its results
// file survives; orchestrator would "pm clear" between methods and wipe it.
execution = (System.getenv("LD_EVENT_BENCH") == "1") ? "HOST" : "ANDROIDX_TEST_ORCHESTRATOR"

// EventPersistenceBenchmark reports its measurements on stdout, which Gradle otherwise
// swallows, and it is worth re-running even when nothing has changed. Both only apply when
// LD_EVENT_BENCH is set, which is also what un-skips the benchmark, so an ordinary test run
// is unaffected.
unitTests.all { test ->
if (System.getenv("LD_EVENT_BENCH") == "1") {
test.testLogging.showStandardStreams = true
test.outputs.upToDateWhen { false }
}
}
}

buildFeatures {
Expand Down Expand Up @@ -79,7 +99,7 @@ ext.versions = [
"jacksonDatabind": "2.10.5.1",
"junit": "4.13",
"launchdarklyJavaSdkCommon": "2.4.0",
"launchdarklyJavaSdkInternal": "1.9.0",
"launchdarklyJavaSdkInternal": "1.12.2",
"launchdarklyLogging": "1.1.1",
"okhttp": "4.12.0",
"testHelpers": "2.1.0",
Expand All @@ -106,7 +126,11 @@ dependencies {
testImplementation("junit:junit:${versions.junit}")
testImplementation("org.easymock:easymock:4.3")
testImplementation("com.launchdarkly:test-helpers:${versions.testHelpers}")
// The test-helpers class copied into src/test compiles against Guava, which test-helpers only
// brings in at runtime. Keep this at the version it resolves to.
testCompileOnly("com.google.guava:guava:32.0.1-jre")
testImplementation(project(":shared-test-code"))
testImplementation("com.squareup.okhttp3:mockwebserver:${versions.okhttp}")

androidTestImplementation("junit:junit:${versions.junit}")
androidTestImplementation("com.squareup.okhttp3:mockwebserver:${versions.okhttp}")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package com.launchdarkly.sdk.android;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;

/**
* The way expiry opens a batch on Android before API 26, run on whatever device is attached: the JVM tests
* cannot reach it.
*/
@RunWith(AndroidJUnit4.class)
public class BatchLocksAndroidTest {
private final File directory =
new File(ApplicationProvider.getApplicationContext().getCacheDir(), "batch-locks-test");

@Before
public void createDirectory() {
assertTrue(directory.isDirectory() || directory.mkdirs());
}

@After
public void deleteDirectory() {
File[] files = directory.listFiles();
if (files != null) {
for (File file : files) {
file.delete();
}
}
directory.delete();
}

@Test
public void neverCreatesABatchThatHasGone() throws IOException {
File gone = new File(directory, "ready-gone-1");
try {
BatchLocks.openThroughParcelFileDescriptor(gone).close();
fail("opened a batch that is not there");
} catch (FileNotFoundException expected) {
// What expiry takes for a batch someone else has dealt with.
}
assertFalse(gone.exists());
}

@Test
public void locksABatchExclusivelyAndLeavesItAsItWas() throws IOException {
File batch = new File(directory, "ready-there-1");
byte[] contents = { 1, 2, 3 };
try (FileOutputStream out = new FileOutputStream(batch)) {
out.write(contents);
}

try (FileChannel channel = BatchLocks.openThroughParcelFileDescriptor(batch);
FileLock exclusive = channel.tryLock()) {
assertNotNull(exclusive);
assertFalse(exclusive.isShared());
}

assertEquals(contents.length, batch.length());
}
}
Loading
Loading