react-native-nitro-logger 0.1.0

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.
Files changed (205) hide show
  1. package/LICENSE +20 -0
  2. package/NitroLogger.podspec +29 -0
  3. package/README.md +214 -0
  4. package/android/CMakeLists.txt +24 -0
  5. package/android/build.gradle +124 -0
  6. package/android/src/main/AndroidManifest.xml +2 -0
  7. package/android/src/main/cpp/cpp-adapter.cpp +11 -0
  8. package/android/src/main/java/com/margelo/nitro/nitrologger/AndroidPlatformIo.kt +100 -0
  9. package/android/src/main/java/com/margelo/nitro/nitrologger/HybridFileSink.kt +292 -0
  10. package/android/src/main/java/com/margelo/nitro/nitrologger/HybridNativeConsoleSink.kt +23 -0
  11. package/android/src/main/java/com/margelo/nitro/nitrologger/LogFileWriter.kt +1328 -0
  12. package/android/src/main/java/com/margelo/nitro/nitrologger/LogRotationPolicy.kt +186 -0
  13. package/android/src/main/java/com/margelo/nitro/nitrologger/LogSecureFile.kt +80 -0
  14. package/android/src/main/java/com/margelo/nitro/nitrologger/LogWriterRegistry.kt +420 -0
  15. package/android/src/main/java/com/margelo/nitro/nitrologger/NativeConsoleWriter.kt +237 -0
  16. package/android/src/main/java/com/margelo/nitro/nitrologger/NitroLoggerPackage.kt +22 -0
  17. package/android/src/main/java/com/margelo/nitro/nitrologger/PlatformIo.kt +165 -0
  18. package/docs/PARITY.md +330 -0
  19. package/docs/PRIVACY.md +341 -0
  20. package/eslint-plugin/README.md +238 -0
  21. package/eslint-plugin/index.js +62 -0
  22. package/eslint-plugin/rules/literal-subsystem.js +102 -0
  23. package/eslint-plugin/rules/no-computed-metadata-key.js +174 -0
  24. package/eslint-plugin/rules/no-derived-correlation.js +171 -0
  25. package/eslint-plugin/rules/no-dynamic-message.js +60 -0
  26. package/eslint-plugin/shared.js +1948 -0
  27. package/ios/Gzip.swift +203 -0
  28. package/ios/HybridFileSink.swift +291 -0
  29. package/ios/HybridNativeConsoleSink.swift +20 -0
  30. package/ios/LogFileWriter.swift +1280 -0
  31. package/ios/LogSecureFile.swift +296 -0
  32. package/ios/LogWriterRegistry.swift +444 -0
  33. package/ios/NativeConsoleWriter.swift +180 -0
  34. package/lib/module/Logger.js +381 -0
  35. package/lib/module/Logger.js.map +1 -0
  36. package/lib/module/ScopedLogger.js +70 -0
  37. package/lib/module/ScopedLogger.js.map +1 -0
  38. package/lib/module/config.js +23 -0
  39. package/lib/module/config.js.map +1 -0
  40. package/lib/module/destinations/Batcher.js +647 -0
  41. package/lib/module/destinations/Batcher.js.map +1 -0
  42. package/lib/module/destinations/ConsoleDestination.js +51 -0
  43. package/lib/module/destinations/ConsoleDestination.js.map +1 -0
  44. package/lib/module/destinations/FileDestination.js +360 -0
  45. package/lib/module/destinations/FileDestination.js.map +1 -0
  46. package/lib/module/destinations/NativeConsoleDestination.js +170 -0
  47. package/lib/module/destinations/NativeConsoleDestination.js.map +1 -0
  48. package/lib/module/destinations/types.js +4 -0
  49. package/lib/module/destinations/types.js.map +1 -0
  50. package/lib/module/formatters/DefaultFormatter.js +136 -0
  51. package/lib/module/formatters/DefaultFormatter.js.map +1 -0
  52. package/lib/module/formatters/JsonLinesFormatter.js +162 -0
  53. package/lib/module/formatters/JsonLinesFormatter.js.map +1 -0
  54. package/lib/module/formatters/timestamp.js +15 -0
  55. package/lib/module/formatters/timestamp.js.map +1 -0
  56. package/lib/module/formatters/types.js +4 -0
  57. package/lib/module/formatters/types.js.map +1 -0
  58. package/lib/module/index.js +31 -0
  59. package/lib/module/index.js.map +1 -0
  60. package/lib/module/integrations/appState.js +81 -0
  61. package/lib/module/integrations/appState.js.map +1 -0
  62. package/lib/module/integrations/errorHandler.js +166 -0
  63. package/lib/module/integrations/errorHandler.js.map +1 -0
  64. package/lib/module/integrations/sanitizeError.js +238 -0
  65. package/lib/module/integrations/sanitizeError.js.map +1 -0
  66. package/lib/module/levels.js +35 -0
  67. package/lib/module/levels.js.map +1 -0
  68. package/lib/module/metadata.js +52 -0
  69. package/lib/module/metadata.js.map +1 -0
  70. package/lib/module/package.json +1 -0
  71. package/lib/module/privacy.js +349 -0
  72. package/lib/module/privacy.js.map +1 -0
  73. package/lib/module/specs/FileSink.nitro.js +4 -0
  74. package/lib/module/specs/FileSink.nitro.js.map +1 -0
  75. package/lib/module/specs/NativeConsoleSink.nitro.js +4 -0
  76. package/lib/module/specs/NativeConsoleSink.nitro.js.map +1 -0
  77. package/lib/module/types.js +4 -0
  78. package/lib/module/types.js.map +1 -0
  79. package/lib/module/utf8.js +42 -0
  80. package/lib/module/utf8.js.map +1 -0
  81. package/lib/typescript/package.json +1 -0
  82. package/lib/typescript/src/Logger.d.ts +122 -0
  83. package/lib/typescript/src/Logger.d.ts.map +1 -0
  84. package/lib/typescript/src/ScopedLogger.d.ts +36 -0
  85. package/lib/typescript/src/ScopedLogger.d.ts.map +1 -0
  86. package/lib/typescript/src/config.d.ts +12 -0
  87. package/lib/typescript/src/config.d.ts.map +1 -0
  88. package/lib/typescript/src/destinations/Batcher.d.ts +244 -0
  89. package/lib/typescript/src/destinations/Batcher.d.ts.map +1 -0
  90. package/lib/typescript/src/destinations/ConsoleDestination.d.ts +27 -0
  91. package/lib/typescript/src/destinations/ConsoleDestination.d.ts.map +1 -0
  92. package/lib/typescript/src/destinations/FileDestination.d.ts +200 -0
  93. package/lib/typescript/src/destinations/FileDestination.d.ts.map +1 -0
  94. package/lib/typescript/src/destinations/NativeConsoleDestination.d.ts +86 -0
  95. package/lib/typescript/src/destinations/NativeConsoleDestination.d.ts.map +1 -0
  96. package/lib/typescript/src/destinations/types.d.ts +19 -0
  97. package/lib/typescript/src/destinations/types.d.ts.map +1 -0
  98. package/lib/typescript/src/formatters/DefaultFormatter.d.ts +22 -0
  99. package/lib/typescript/src/formatters/DefaultFormatter.d.ts.map +1 -0
  100. package/lib/typescript/src/formatters/JsonLinesFormatter.d.ts +73 -0
  101. package/lib/typescript/src/formatters/JsonLinesFormatter.d.ts.map +1 -0
  102. package/lib/typescript/src/formatters/timestamp.d.ts +6 -0
  103. package/lib/typescript/src/formatters/timestamp.d.ts.map +1 -0
  104. package/lib/typescript/src/formatters/types.d.ts +27 -0
  105. package/lib/typescript/src/formatters/types.d.ts.map +1 -0
  106. package/lib/typescript/src/index.d.ts +34 -0
  107. package/lib/typescript/src/index.d.ts.map +1 -0
  108. package/lib/typescript/src/integrations/appState.d.ts +33 -0
  109. package/lib/typescript/src/integrations/appState.d.ts.map +1 -0
  110. package/lib/typescript/src/integrations/errorHandler.d.ts +55 -0
  111. package/lib/typescript/src/integrations/errorHandler.d.ts.map +1 -0
  112. package/lib/typescript/src/integrations/sanitizeError.d.ts +89 -0
  113. package/lib/typescript/src/integrations/sanitizeError.d.ts.map +1 -0
  114. package/lib/typescript/src/levels.d.ts +9 -0
  115. package/lib/typescript/src/levels.d.ts.map +1 -0
  116. package/lib/typescript/src/metadata.d.ts +23 -0
  117. package/lib/typescript/src/metadata.d.ts.map +1 -0
  118. package/lib/typescript/src/privacy.d.ts +103 -0
  119. package/lib/typescript/src/privacy.d.ts.map +1 -0
  120. package/lib/typescript/src/specs/FileSink.nitro.d.ts +131 -0
  121. package/lib/typescript/src/specs/FileSink.nitro.d.ts.map +1 -0
  122. package/lib/typescript/src/specs/NativeConsoleSink.nitro.d.ts +21 -0
  123. package/lib/typescript/src/specs/NativeConsoleSink.nitro.d.ts.map +1 -0
  124. package/lib/typescript/src/types.d.ts +37 -0
  125. package/lib/typescript/src/types.d.ts.map +1 -0
  126. package/lib/typescript/src/utf8.d.ts +15 -0
  127. package/lib/typescript/src/utf8.d.ts.map +1 -0
  128. package/nitro.json +33 -0
  129. package/nitrogen/generated/android/c++/JAppendResult.hpp +79 -0
  130. package/nitrogen/generated/android/c++/JClearOutcome.hpp +88 -0
  131. package/nitrogen/generated/android/c++/JFlushOutcome.hpp +81 -0
  132. package/nitrogen/generated/android/c++/JHybridFileSinkSpec.cpp +120 -0
  133. package/nitrogen/generated/android/c++/JHybridFileSinkSpec.hpp +69 -0
  134. package/nitrogen/generated/android/c++/JHybridNativeConsoleSinkSpec.cpp +71 -0
  135. package/nitrogen/generated/android/c++/JHybridNativeConsoleSinkSpec.hpp +64 -0
  136. package/nitrogen/generated/android/c++/JRejectReason.hpp +64 -0
  137. package/nitrogen/generated/android/c++/JRotationConfig.hpp +77 -0
  138. package/nitrogen/generated/android/c++/JSinkStatus.hpp +69 -0
  139. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrologger/AppendResult.kt +76 -0
  140. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrologger/ClearOutcome.kt +66 -0
  141. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrologger/FlushOutcome.kt +81 -0
  142. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrologger/HybridFileSinkSpec.kt +80 -0
  143. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrologger/HybridNativeConsoleSinkSpec.kt +58 -0
  144. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrologger/RejectReason.kt +25 -0
  145. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrologger/RotationConfig.kt +76 -0
  146. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrologger/SinkStatus.kt +66 -0
  147. package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrologger/nitrologgerOnLoad.kt +35 -0
  148. package/nitrogen/generated/android/nitrologger+autolinking.cmake +83 -0
  149. package/nitrogen/generated/android/nitrologger+autolinking.gradle +27 -0
  150. package/nitrogen/generated/android/nitrologgerOnLoad.cpp +70 -0
  151. package/nitrogen/generated/android/nitrologgerOnLoad.hpp +34 -0
  152. package/nitrogen/generated/ios/NitroLogger+autolinking.rb +62 -0
  153. package/nitrogen/generated/ios/NitroLogger-Swift-Cxx-Bridge.cpp +50 -0
  154. package/nitrogen/generated/ios/NitroLogger-Swift-Cxx-Bridge.hpp +216 -0
  155. package/nitrogen/generated/ios/NitroLogger-Swift-Cxx-Umbrella.hpp +69 -0
  156. package/nitrogen/generated/ios/NitroLoggerAutolinking.mm +41 -0
  157. package/nitrogen/generated/ios/NitroLoggerAutolinking.swift +38 -0
  158. package/nitrogen/generated/ios/c++/HybridFileSinkSpecSwift.cpp +11 -0
  159. package/nitrogen/generated/ios/c++/HybridFileSinkSpecSwift.hpp +150 -0
  160. package/nitrogen/generated/ios/c++/HybridNativeConsoleSinkSpecSwift.cpp +11 -0
  161. package/nitrogen/generated/ios/c++/HybridNativeConsoleSinkSpecSwift.hpp +87 -0
  162. package/nitrogen/generated/ios/swift/AppendResult.swift +60 -0
  163. package/nitrogen/generated/ios/swift/ClearOutcome.swift +50 -0
  164. package/nitrogen/generated/ios/swift/FlushOutcome.swift +59 -0
  165. package/nitrogen/generated/ios/swift/HybridFileSinkSpec.swift +61 -0
  166. package/nitrogen/generated/ios/swift/HybridFileSinkSpec_cxx.swift +227 -0
  167. package/nitrogen/generated/ios/swift/HybridNativeConsoleSinkSpec.swift +56 -0
  168. package/nitrogen/generated/ios/swift/HybridNativeConsoleSinkSpec_cxx.swift +148 -0
  169. package/nitrogen/generated/ios/swift/RejectReason.swift +48 -0
  170. package/nitrogen/generated/ios/swift/RotationConfig.swift +93 -0
  171. package/nitrogen/generated/ios/swift/SinkStatus.swift +44 -0
  172. package/nitrogen/generated/shared/c++/AppendResult.hpp +105 -0
  173. package/nitrogen/generated/shared/c++/ClearOutcome.hpp +96 -0
  174. package/nitrogen/generated/shared/c++/FlushOutcome.hpp +107 -0
  175. package/nitrogen/generated/shared/c++/HybridFileSinkSpec.cpp +28 -0
  176. package/nitrogen/generated/shared/c++/HybridFileSinkSpec.hpp +84 -0
  177. package/nitrogen/generated/shared/c++/HybridNativeConsoleSinkSpec.cpp +22 -0
  178. package/nitrogen/generated/shared/c++/HybridNativeConsoleSinkSpec.hpp +64 -0
  179. package/nitrogen/generated/shared/c++/RejectReason.hpp +84 -0
  180. package/nitrogen/generated/shared/c++/RotationConfig.hpp +103 -0
  181. package/nitrogen/generated/shared/c++/SinkStatus.hpp +95 -0
  182. package/package.json +151 -0
  183. package/src/Logger.ts +417 -0
  184. package/src/ScopedLogger.ts +94 -0
  185. package/src/config.ts +25 -0
  186. package/src/destinations/Batcher.ts +805 -0
  187. package/src/destinations/ConsoleDestination.ts +60 -0
  188. package/src/destinations/FileDestination.ts +473 -0
  189. package/src/destinations/NativeConsoleDestination.ts +220 -0
  190. package/src/destinations/types.ts +19 -0
  191. package/src/formatters/DefaultFormatter.ts +150 -0
  192. package/src/formatters/JsonLinesFormatter.ts +195 -0
  193. package/src/formatters/timestamp.ts +12 -0
  194. package/src/formatters/types.ts +29 -0
  195. package/src/index.tsx +106 -0
  196. package/src/integrations/appState.ts +111 -0
  197. package/src/integrations/errorHandler.ts +223 -0
  198. package/src/integrations/sanitizeError.ts +287 -0
  199. package/src/levels.ts +35 -0
  200. package/src/metadata.ts +52 -0
  201. package/src/privacy.ts +389 -0
  202. package/src/specs/FileSink.nitro.ts +144 -0
  203. package/src/specs/NativeConsoleSink.nitro.ts +21 -0
  204. package/src/types.ts +45 -0
  205. package/src/utf8.ts +39 -0
@@ -0,0 +1,647 @@
1
+ "use strict";
2
+
3
+ import { utf8Length } from "../utf8.js";
4
+
5
+ /**
6
+ * The part of a `FileSink` the batcher drives. Narrow on purpose: it is what
7
+ * lets the whole backpressure and loss protocol be tested against a scripted
8
+ * double, with no native runtime and no filesystem.
9
+ */
10
+
11
+ /** Entries that never reached the file, and the bytes they would have been. */
12
+
13
+ /** Why the sink cut this handle off. Both are terminal for the batcher. */
14
+
15
+ /**
16
+ * What a bounded drain achieved.
17
+ *
18
+ * Deliberately not the sink's `FlushOutcome`: the sink reports monotonic
19
+ * per-handle totals, whereas `unreportedEntries` / `unreportedBytes` are the
20
+ * losses that still have no notice in the file. That is the number a caller
21
+ * can act on, and conflating the two is how "we already logged that" turns
22
+ * into a loss no one ever hears about.
23
+ */
24
+
25
+ /** Monotonic totals, JS-side and sink-side, at one instant. */
26
+
27
+ /** How far a bounded drain has got. See {@link advanced}. */
28
+
29
+ const DEFAULTS = {
30
+ batchBytes: 4096,
31
+ flushIntervalMs: 100,
32
+ maxPendingEntries: 1000,
33
+ maxPendingBytes: 512 * 1024,
34
+ watermarkBytes: 256 * 1024,
35
+ maxBatchBytes: 256 * 1024
36
+ };
37
+
38
+ /** Upper bound on any deadline handed to the sink, in milliseconds. */
39
+ const MAX_DEADLINE_MS = 30_000;
40
+
41
+ /** Consecutive no-progress rounds before a bounded drain gives up. */
42
+ const MAX_STALLS = 8;
43
+
44
+ /** Pushes per timer tick, so catching up cannot monopolise the JS thread. */
45
+ const PUSHES_PER_TICK = 4;
46
+
47
+ /**
48
+ * Buffers formatted records and feeds them to a sink under backpressure.
49
+ *
50
+ * Three things happen here that do not happen anywhere else.
51
+ *
52
+ * **Backpressure.** The sink's queue is bounded, so once it passes the
53
+ * watermark the batcher stops pushing and polls `getStatus()` instead — which
54
+ * is why that call is specified never to wait behind writer I/O. Records
55
+ * accumulate in the JS buffer meanwhile, itself bounded by an entry count and
56
+ * a byte count.
57
+ *
58
+ * **Drop-newest.** When the JS buffer is full the arriving record is dropped,
59
+ * not the oldest one held. Under a sustained overload the two policies lose
60
+ * the same volume; they differ in what survives, and the older records are
61
+ * the ones with the context explaining how the overload started.
62
+ *
63
+ * **Loss is owed until it is written.** Every drop — here or in the sink —
64
+ * accrues to a counter that is only cleared once a notice describing it has
65
+ * been accepted, and is re-armed if the flush that should have made that
66
+ * notice durable says otherwise. A loss can therefore be reported twice; it
67
+ * cannot be reported zero times. Silence has to mean nothing was lost, or the
68
+ * counters are decoration.
69
+ */
70
+ export class Batcher {
71
+ pending = [];
72
+ pendingBytes = 0;
73
+ paused = false;
74
+ fenced = false;
75
+ disposed = false;
76
+ /**
77
+ * A notice could not be delivered on its own — unrenderable, or refused by
78
+ * the sink — and nothing about ticking again would change that.
79
+ *
80
+ * The debt stays owed and still shows in `unreported()`; what stops is the
81
+ * retrying on a timer, which would go on for the life of the process
82
+ * achieving nothing. The next record to arrive reopens it — that retry
83
+ * rides a batch that carries the record, so it cannot spin — as does an
84
+ * explicit `flush()`.
85
+ */
86
+ noticeBlocked = false;
87
+ /** Highest sink totals seen, and every byte this side has dropped. */
88
+ observed = zeroCursor();
89
+ /** Covered by a notice the sink has accepted. */
90
+ acked = zeroCursor();
91
+ /** Covered by a notice a durable flush has confirmed. */
92
+ confirmed = zeroCursor();
93
+ degraded = 0;
94
+ constructor(target, options) {
95
+ this.target = target;
96
+ this.renderNotice = options.renderNotice;
97
+ this.onFenced = options.onFenced;
98
+ this.batchBytes = positive(options.batchBytes, DEFAULTS.batchBytes);
99
+ this.flushIntervalMs = positive(options.flushIntervalMs, DEFAULTS.flushIntervalMs);
100
+ this.maxPendingEntries = positive(options.maxPendingEntries, DEFAULTS.maxPendingEntries);
101
+ this.maxPendingBytes = positive(options.maxPendingBytes, DEFAULTS.maxPendingBytes);
102
+ this.watermarkBytes = positive(options.watermarkBytes, DEFAULTS.watermarkBytes);
103
+ this.maxBatchBytes = positive(options.maxBatchBytes, DEFAULTS.maxBatchBytes);
104
+ }
105
+
106
+ // ── Producing ───────────────────────────────────────────────────────────
107
+
108
+ /**
109
+ * Buffer one formatted record. Never performs I/O beyond handing a full
110
+ * batch to the sink, and never throws: a logging call must not fail the
111
+ * code that made it.
112
+ */
113
+ add(record) {
114
+ if (this.disposed || this.fenced) {
115
+ this.dropped(record);
116
+ return;
117
+ }
118
+ const bytes = utf8Length(record) + 1; // the record's own newline
119
+ if (this.pending.length >= this.maxPendingEntries || this.pendingBytes + bytes > this.maxPendingBytes) {
120
+ this.dropped(record, bytes);
121
+ this.ensureTimer();
122
+ return;
123
+ }
124
+ this.pending.push({
125
+ text: record,
126
+ bytes
127
+ });
128
+ this.pendingBytes += bytes;
129
+ // A record to ride with is a fresh chance for a notice the sink refused
130
+ // earlier, and the reason it refused is usually temporary — a queue that
131
+ // was full a moment ago. Retrying on this event cannot spin the way a
132
+ // timer can: the batch carries a record, so it makes progress either way,
133
+ // and if the notice fails again the dead ends below block it again.
134
+ // Waiting instead for the next explicit flush means a process that dies
135
+ // first reports the loss zero times.
136
+ this.noticeBlocked = false;
137
+ if (!this.paused && this.pendingBytes >= this.batchBytes) {
138
+ this.pushOnce();
139
+ }
140
+ this.ensureTimer();
141
+ }
142
+
143
+ /**
144
+ * Record a loss that happened before the batcher saw it — a record that
145
+ * could not be rendered, or one too large to be rendered honestly. It is
146
+ * owed a notice on exactly the same terms as anything dropped here.
147
+ */
148
+ noteLoss(entries, bytes) {
149
+ this.observed.localEntries += toCount(entries);
150
+ this.observed.localBytes += toCount(bytes);
151
+ this.ensureTimer();
152
+ }
153
+
154
+ /** Losses with no notice in the file yet. */
155
+ unreported() {
156
+ return this.delta();
157
+ }
158
+
159
+ /** Bytes buffered on this side, not yet handed to the sink. */
160
+ bufferedBytes() {
161
+ return this.pendingBytes;
162
+ }
163
+
164
+ /**
165
+ * Payload-free bitmask of what has stopped working underneath — rotation,
166
+ * gzip, prune, sidecar, protection.
167
+ *
168
+ * This mirrors the sink's own mask, which accumulates bits and drops them
169
+ * only when a durable purge baselines everything. That is deliberate: these
170
+ * are things an app wants to know happened *at all*, and a mask that cleared
171
+ * itself the moment the next batch succeeded would report nothing the one
172
+ * time it mattered.
173
+ */
174
+ degradation() {
175
+ return this.degraded;
176
+ }
177
+ isFenced() {
178
+ return this.fenced;
179
+ }
180
+
181
+ // ── Draining ────────────────────────────────────────────────────────────
182
+
183
+ /**
184
+ * Drain to the sink and fsync, bounded by a wall-clock deadline.
185
+ *
186
+ * Backpressure is overridden for the duration: the whole point of a flush
187
+ * is to push through a full queue rather than wait for it to clear, so a
188
+ * rejected batch is followed by a bounded sink flush and retried.
189
+ *
190
+ * The postcondition is honest rather than absolute. Under a disk that stays
191
+ * full, this returns `durable: false` with the losses preserved — the
192
+ * alternative, insisting everything is either durable or noticed, is a
193
+ * promise no implementation can keep.
194
+ */
195
+ flush(deadlineMs) {
196
+ this.cancelTimer();
197
+ if (this.disposed || this.fenced) return this.outcome(false, false, 0);
198
+ const deadlineAt = Date.now() + clampDeadline(deadlineMs);
199
+ this.paused = false;
200
+ // An explicit flush is the retry: a notice the sink refused on its own
201
+ // gets one more chance here before being set aside again.
202
+ this.noticeBlocked = false;
203
+ let timedOut = false;
204
+ let stalls = 0;
205
+ let attempts = 0;
206
+ const maxAttempts = this.maxPendingEntries + MAX_STALLS * 2 + 16;
207
+ while (this.pending.length > 0 || this.owesNotice()) {
208
+ if (attempts >= maxAttempts || Date.now() >= deadlineAt) {
209
+ timedOut = true;
210
+ break;
211
+ }
212
+ attempts += 1;
213
+ const before = this.position();
214
+ const result = this.pushOnce();
215
+ if (result === 'empty' || result === 'fenced') break;
216
+ if (result === 'full') {
217
+ // Ask the sink to write what it has, then retry.
218
+ const remaining = deadlineAt - Date.now();
219
+ if (remaining <= 0) {
220
+ timedOut = true;
221
+ break;
222
+ }
223
+ const mid = this.targetFlush(remaining);
224
+ if (mid.timedOut) timedOut = true;
225
+ }
226
+
227
+ // Progress is MEASURED, never inferred from the result: a notice-only
228
+ // batch that fails removes no records and settles no debt, and a sink
229
+ // that finds a fresh loss on every append can hold the debt constant
230
+ // indefinitely — both look like progress to a check that only asks
231
+ // whether the push said 'failed'.
232
+ if (advanced(before, this.position())) {
233
+ stalls = 0;
234
+ } else {
235
+ stalls += 1;
236
+ if (stalls >= MAX_STALLS) break;
237
+ }
238
+ }
239
+ const final = this.targetFlush(Math.max(0, deadlineAt - Date.now()));
240
+ if (final.timedOut) timedOut = true;
241
+ const settled = final.durable && this.pending.length === 0 && !this.owesNotice();
242
+ if (settled) {
243
+ // Every notice accepted so far is now on disk.
244
+ this.confirmed = {
245
+ ...this.acked
246
+ };
247
+ } else {
248
+ // An accepted notice that no flush has confirmed is not a notice yet.
249
+ // Re-arming risks writing it twice, which beats losing it.
250
+ this.acked = {
251
+ ...this.confirmed
252
+ };
253
+ }
254
+
255
+ // The final sync is itself a place losses are discovered — a batch the
256
+ // writer could not land shows up in the counters it returns. Re-arm, or a
257
+ // loss learned about here waits for the next log call to be reported, and
258
+ // an app that has stopped logging never makes one.
259
+ this.ensureTimer();
260
+ return this.outcome(settled, timedOut, final.pendingBytes);
261
+ }
262
+
263
+ /**
264
+ * Release timers and let the buffer go. Idempotent.
265
+ *
266
+ * Deliberately does not flush: `LogDestination` calls `flush()` before
267
+ * `dispose()`, and a dispose that quietly blocked on a stalled disk would
268
+ * turn tearing down a destination into a hang.
269
+ */
270
+ dispose() {
271
+ this.cancelTimer();
272
+ this.disposed = true;
273
+ this.pending = [];
274
+ this.pendingBytes = 0;
275
+ }
276
+
277
+ /**
278
+ * Forget everything buffered and start the loss counters over, returning
279
+ * what was discarded.
280
+ *
281
+ * This is the purge path. The counts go back to the caller instead of into
282
+ * a notice, because a "4,182 entries dropped" line written into a file that
283
+ * was just cleared for compliance reasons describes the clearing, and the
284
+ * caller already knows it cleared the file.
285
+ */
286
+ discard() {
287
+ const discardedEntries = this.pending.length;
288
+ const discardedBytes = this.pendingBytes;
289
+ this.pending = [];
290
+ this.pendingBytes = 0;
291
+ this.syncCounters();
292
+ const owed = this.delta();
293
+ this.baseline();
294
+ this.paused = false;
295
+ return {
296
+ entries: discardedEntries + owed.entries,
297
+ bytes: discardedBytes + owed.bytes
298
+ };
299
+ }
300
+
301
+ /**
302
+ * Resume against a fresh generation after the owner has rebound.
303
+ *
304
+ * The sink cursors are re-read from scratch rather than carried over,
305
+ * because the old totals are not a baseline for the new handle's. Whether
306
+ * the sink resets its per-handle counters on rebind or keeps them running
307
+ * is not something this side can know — and getting it wrong is silent in
308
+ * the worse direction: keeping a stale maximum would swallow every new loss
309
+ * smaller than the pre-purge total, reporting it zero times.
310
+ *
311
+ * Local counters are deliberately left alone. Records this side dropped
312
+ * after the fence went up are real drops of real entries, and they belong
313
+ * to the new file as much as to the old one.
314
+ */
315
+ rebind() {
316
+ this.fenced = false;
317
+ this.paused = false;
318
+ this.noticeBlocked = false;
319
+ this.observed.sinkEntries = 0;
320
+ this.observed.sinkBytes = 0;
321
+ this.syncCounters();
322
+ this.acked.sinkEntries = this.observed.sinkEntries;
323
+ this.acked.sinkBytes = this.observed.sinkBytes;
324
+ this.confirmed.sinkEntries = this.observed.sinkEntries;
325
+ this.confirmed.sinkBytes = this.observed.sinkBytes;
326
+ }
327
+
328
+ // ── Internals ───────────────────────────────────────────────────────────
329
+
330
+ /**
331
+ * Hand at most one batch to the sink.
332
+ *
333
+ * The loss snapshot is taken BEFORE the call and acknowledged to that
334
+ * snapshot rather than to the totals the call returns. A drop that happens
335
+ * during this very append is not described by the notice riding in it, and
336
+ * acknowledging the post-call totals would bury it.
337
+ */
338
+ pushOnce() {
339
+ const lines = [];
340
+ let entryCount = 0;
341
+ let entryBytes = 0;
342
+ for (const item of this.pending) {
343
+ if (entryCount > 0 && entryBytes + item.bytes > this.maxBatchBytes) break;
344
+ lines.push(item.text);
345
+ entryBytes += item.bytes;
346
+ entryCount += 1;
347
+ }
348
+ const snapshot = {
349
+ ...this.observed
350
+ };
351
+ const owed = this.delta();
352
+ let carriesNotice = false;
353
+ if (!this.noticeBlocked && (owed.entries > 0 || owed.bytes > 0)) {
354
+ const notice = this.noticeText(owed);
355
+ if (notice !== undefined) {
356
+ lines.push(notice);
357
+ carriesNotice = true;
358
+ } else if (entryCount === 0) {
359
+ // A notice that will not render, and nothing else to send. Trying
360
+ // again in a hundred milliseconds will produce the same nothing, so
361
+ // the debt is set aside rather than retried on a timer for the life
362
+ // of the process. It is still owed, and an explicit flush reopens it.
363
+ this.noticeBlocked = true;
364
+ }
365
+ }
366
+ if (lines.length === 0) return 'empty';
367
+
368
+ // Whether this batch is carrying the notice and nothing else, which is
369
+ // what makes a rejection unrecoverable by retrying: there is no record to
370
+ // give up to make it smaller, and no smaller notice to send.
371
+ const noticeOnly = entryCount === 0;
372
+
373
+ // The notice goes after the records it does not describe, so a reader
374
+ // meets the surviving entries first and the gap where the others were.
375
+ const batch = `${lines.join('\n')}\n`;
376
+ let result;
377
+ try {
378
+ result = this.target.appendBatch(batch, lines.length);
379
+ } catch {
380
+ // A throwing sink is a failing sink. The batch is gone either way.
381
+ this.loseHead(entryCount, entryBytes);
382
+ if (noticeOnly) this.noticeBlocked = true;
383
+ return 'failed';
384
+ }
385
+ this.observeCounts(result.lostEntries, result.lostBytes, result.degraded);
386
+ if (result.accepted) {
387
+ this.loseHead(entryCount, 0, false);
388
+ if (carriesNotice) this.acked = snapshot;
389
+ if (toCount(result.queuedBytes) >= this.watermarkBytes) this.paused = true;
390
+ return 'sent';
391
+ }
392
+ const reason = result.rejectReason ?? 'failed';
393
+ if (reason === 'staleGeneration' || reason === 'closed') {
394
+ this.fence(reason);
395
+ return 'fenced';
396
+ }
397
+ if (reason === 'full') {
398
+ // An empty sink that still refuses means the batch is larger than the
399
+ // sink can ever hold, not that it is busy. Waiting for room that will
400
+ // never come wedges every later record behind this one.
401
+ if (toCount(result.queuedBytes) === 0) {
402
+ if (carriesNotice) {
403
+ // The notice may be the whole reason this did not fit, so it goes
404
+ // first — before any record is given up for it. Setting it aside
405
+ // beats pausing on a sink that has already given its final answer:
406
+ // the debt is kept and offered again on the next explicit flush,
407
+ // and meanwhile records are not held behind a line about old ones.
408
+ this.noticeBlocked = true;
409
+ return 'failed';
410
+ }
411
+ const head = this.pending[0];
412
+ if (head !== undefined) {
413
+ // Records alone, and still too big: give up the oldest and try a
414
+ // smaller batch.
415
+ this.loseHead(1, head.bytes);
416
+ }
417
+ return 'failed';
418
+ }
419
+ this.paused = true;
420
+ return 'full';
421
+ }
422
+ this.loseHead(entryCount, entryBytes);
423
+ // A notice-only batch the sink rejected outright leaves the state exactly
424
+ // as it was: nothing removed, nothing settled. Retrying it on the timer
425
+ // is a loop with no exit.
426
+ if (noticeOnly) this.noticeBlocked = true;
427
+ return 'failed';
428
+ }
429
+
430
+ /**
431
+ * Remove the batch's records from the head of the buffer, optionally
432
+ * counting them as lost.
433
+ */
434
+ loseHead(count, bytes, lost = true) {
435
+ if (count === 0) return;
436
+ const removed = this.pending.splice(0, count);
437
+ for (const item of removed) this.pendingBytes -= item.bytes;
438
+ if (this.pendingBytes < 0) this.pendingBytes = 0;
439
+ if (lost) {
440
+ this.observed.localEntries += count;
441
+ this.observed.localBytes += bytes;
442
+ }
443
+ }
444
+ dropped(record, bytes) {
445
+ this.observed.localEntries += 1;
446
+ this.observed.localBytes += bytes ?? utf8Length(record) + 1;
447
+ }
448
+ fence(reason) {
449
+ // Pre-purge records must never be replayed into a post-purge file, and a
450
+ // notice about them is a statement about data that was deliberately
451
+ // deleted. Both go.
452
+ this.pending = [];
453
+ this.pendingBytes = 0;
454
+ this.syncCounters();
455
+ this.baseline();
456
+ this.fenced = true;
457
+ this.paused = false;
458
+ this.cancelTimer();
459
+ try {
460
+ this.onFenced?.(reason);
461
+ } catch {
462
+ // the owner's problem, not the pipeline's
463
+ }
464
+ }
465
+
466
+ /**
467
+ * Bring the sink's counters up to date without writing anything.
468
+ *
469
+ * Cursors normally advance off append results, which means a loss the sink
470
+ * has recorded but not yet had occasion to report is invisible here. Before
471
+ * drawing a line under the past — a purge, a fence — that window has to be
472
+ * closed, or a loss from the old file crosses over and gets described as if
473
+ * it had happened to the new one.
474
+ */
475
+ syncCounters() {
476
+ try {
477
+ const status = this.target.getStatus();
478
+ this.observeCounts(status.lostEntries, status.lostBytes, status.degraded);
479
+ } catch {
480
+ // An unreadable probe just means the line is drawn where we stand.
481
+ }
482
+ }
483
+
484
+ /** Declare every loss seen so far as settled, reporting none of it. */
485
+ baseline() {
486
+ this.acked = {
487
+ ...this.observed
488
+ };
489
+ this.confirmed = {
490
+ ...this.observed
491
+ };
492
+ }
493
+ noticeText(lost) {
494
+ let text;
495
+ try {
496
+ text = this.renderNotice(lost);
497
+ } catch {
498
+ return undefined;
499
+ }
500
+ return typeof text === 'string' && text.length > 0 ? text : undefined;
501
+ }
502
+ delta() {
503
+ return {
504
+ entries: Math.max(0, this.observed.sinkEntries - this.acked.sinkEntries + (this.observed.localEntries - this.acked.localEntries)),
505
+ bytes: Math.max(0, this.observed.sinkBytes - this.acked.sinkBytes + (this.observed.localBytes - this.acked.localBytes))
506
+ };
507
+ }
508
+ owesNotice() {
509
+ const owed = this.delta();
510
+ return owed.entries > 0 || owed.bytes > 0;
511
+ }
512
+
513
+ /** Where the drain has got to: records still buffered, loss still owed. */
514
+ position() {
515
+ const owed = this.delta();
516
+ return {
517
+ entries: this.pending.length,
518
+ bytes: this.pendingBytes,
519
+ owedEntries: owed.entries,
520
+ owedBytes: owed.bytes
521
+ };
522
+ }
523
+
524
+ /**
525
+ * Fold sink counters in. They are monotonic per handle, so the maximum
526
+ * seen is the truth; a sink that reported a smaller number than last time
527
+ * would otherwise drive the delta negative and cancel a real loss.
528
+ */
529
+ observeCounts(lostEntries, lostBytes, degraded) {
530
+ this.observed.sinkEntries = Math.max(this.observed.sinkEntries, toCount(lostEntries));
531
+ this.observed.sinkBytes = Math.max(this.observed.sinkBytes, toCount(lostBytes));
532
+ this.degraded = toCount(degraded);
533
+ }
534
+ targetFlush(deadlineMs) {
535
+ let outcome;
536
+ try {
537
+ outcome = this.target.flush(clampDeadline(deadlineMs));
538
+ } catch {
539
+ return {
540
+ durable: false,
541
+ timedOut: true,
542
+ pendingBytes: 0,
543
+ queuedBytes: 0,
544
+ lostBytes: this.observed.sinkBytes,
545
+ lostEntries: this.observed.sinkEntries,
546
+ degraded: this.degraded
547
+ };
548
+ }
549
+ this.observeCounts(outcome.lostEntries, outcome.lostBytes, outcome.degraded);
550
+ return outcome;
551
+ }
552
+ outcome(durable, timedOut, sinkPending) {
553
+ const owed = this.delta();
554
+ return {
555
+ durable,
556
+ timedOut,
557
+ // Both sides of the handoff: what never left the JS buffer, plus what
558
+ // the sink took but has not made durable.
559
+ pendingBytes: this.pendingBytes + toCount(sinkPending),
560
+ unreportedEntries: owed.entries,
561
+ unreportedBytes: owed.bytes,
562
+ degraded: this.degraded
563
+ };
564
+ }
565
+
566
+ // ── Timer ───────────────────────────────────────────────────────────────
567
+
568
+ ensureTimer() {
569
+ if (this.timer !== undefined || this.disposed || this.fenced) return;
570
+ // A blocked notice is not a reason to keep ticking: the sink has already
571
+ // refused it, and the next explicit flush is what retries.
572
+ const owed = this.owesNotice() && !this.noticeBlocked;
573
+ if (this.pending.length === 0 && !this.paused && !owed) return;
574
+ this.timer = setTimeout(() => {
575
+ this.timer = undefined;
576
+ this.onTick();
577
+ }, this.flushIntervalMs);
578
+ }
579
+ cancelTimer() {
580
+ if (this.timer !== undefined) {
581
+ clearTimeout(this.timer);
582
+ this.timer = undefined;
583
+ }
584
+ }
585
+ onTick() {
586
+ if (this.disposed || this.fenced) return;
587
+ if (this.paused) {
588
+ // The non-enqueuing probe: this is the call that is specified to be
589
+ // answerable while the writer thread is stalled on disk, and the whole
590
+ // pause/resume cycle rests on that.
591
+ try {
592
+ const status = this.target.getStatus();
593
+ this.observeCounts(status.lostEntries, status.lostBytes, status.degraded);
594
+ if (toCount(status.queuedBytes) < this.watermarkBytes) {
595
+ this.paused = false;
596
+ }
597
+ } catch {
598
+ // stay paused; try again next tick
599
+ }
600
+ }
601
+ if (!this.paused) {
602
+ for (let i = 0; i < PUSHES_PER_TICK; i += 1) {
603
+ const result = this.pushOnce();
604
+ if (result !== 'sent') break;
605
+ if (this.paused) break;
606
+ }
607
+ }
608
+ this.ensureTimer();
609
+ }
610
+ }
611
+ function zeroCursor() {
612
+ return {
613
+ sinkEntries: 0,
614
+ sinkBytes: 0,
615
+ localEntries: 0,
616
+ localBytes: 0
617
+ };
618
+ }
619
+
620
+ /**
621
+ * Did the drain get anywhere between these two positions?
622
+ *
623
+ * The two halves are compared separately rather than summed, because a batch
624
+ * the sink refused moves records out of the buffer and into the debt they now
625
+ * owe a notice — a conserved total, and real progress. Summing them says the
626
+ * drain is stuck at exactly the moment it is working through a failing sink,
627
+ * and abandons the records queued behind the ones it just gave up on.
628
+ */
629
+ function advanced(before, after) {
630
+ if (after.entries < before.entries || after.bytes < before.bytes) return true;
631
+ return after.owedEntries < before.owedEntries || after.owedBytes < before.owedBytes;
632
+ }
633
+
634
+ /** A count from across the bridge; anything not a positive number is zero. */
635
+ function toCount(value) {
636
+ return typeof value === 'number' && Number.isFinite(value) && value > 0 ? Math.floor(value) : 0;
637
+ }
638
+ function positive(value, fallback) {
639
+ return typeof value === 'number' && Number.isFinite(value) && value > 0 ? Math.floor(value) : fallback;
640
+ }
641
+ function clampDeadline(value) {
642
+ if (typeof value !== 'number' || !Number.isFinite(value) || value <= 0) {
643
+ return 0;
644
+ }
645
+ return Math.min(Math.floor(value), MAX_DEADLINE_MS);
646
+ }
647
+ //# sourceMappingURL=Batcher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["utf8Length","DEFAULTS","batchBytes","flushIntervalMs","maxPendingEntries","maxPendingBytes","watermarkBytes","maxBatchBytes","MAX_DEADLINE_MS","MAX_STALLS","PUSHES_PER_TICK","Batcher","pending","pendingBytes","paused","fenced","disposed","noticeBlocked","observed","zeroCursor","acked","confirmed","degraded","constructor","target","options","renderNotice","onFenced","positive","add","record","dropped","bytes","length","ensureTimer","push","text","pushOnce","noteLoss","entries","localEntries","toCount","localBytes","unreported","delta","bufferedBytes","degradation","isFenced","flush","deadlineMs","cancelTimer","outcome","deadlineAt","Date","now","clampDeadline","timedOut","stalls","attempts","maxAttempts","owesNotice","before","position","result","remaining","mid","targetFlush","advanced","final","Math","max","settled","durable","dispose","discard","discardedEntries","discardedBytes","syncCounters","owed","baseline","rebind","sinkEntries","sinkBytes","lines","entryCount","entryBytes","item","snapshot","carriesNotice","notice","noticeText","undefined","noticeOnly","batch","join","appendBatch","loseHead","observeCounts","lostEntries","lostBytes","accepted","queuedBytes","reason","rejectReason","fence","head","count","lost","removed","splice","status","getStatus","owedEntries","owedBytes","sinkPending","unreportedEntries","unreportedBytes","timer","setTimeout","onTick","clearTimeout","i","after","value","Number","isFinite","floor","fallback","min"],"sourceRoot":"../../../src","sources":["destinations/Batcher.ts"],"mappings":"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","ignoreList":[]}