@@ -256,6 +256,106 @@ describe('deliveryApi', () => {
256256 expect ( errorSpy ) . toHaveBeenCalledWith ( 'Failed to add probe invalid-capture-expression:' , jasmine . any ( Error ) )
257257 } )
258258
259+ it ( 'should keep adding the other probes when one probe in the same response fails to initialize' , async ( ) => {
260+ respondWith ( {
261+ nextCursor : 'cursor-1' ,
262+ updates : [
263+ createProbe ( { id : 'valid-before' , where : { typeName : 'test.js' , methodName : 'before' } } ) ,
264+ createProbe ( {
265+ id : 'invalid' ,
266+ where : { typeName : 'test.js' , methodName : 'invalid' } ,
267+ captureSnapshot : false ,
268+ captureExpressions : [
269+ {
270+ name : 'invalid expr' ,
271+ expr : { dsl : 'not a valid identifier!' , json : { ref : 'not a valid identifier!' } } ,
272+ } ,
273+ ] ,
274+ } ) ,
275+ createProbe ( { id : 'valid-after' , where : { typeName : 'test.js' , methodName : 'after' } } ) ,
276+ ] ,
277+ deletions : [ ] ,
278+ } )
279+
280+ startDeliveryApiPolling ( makeConfig ( ) )
281+ await flushPromises ( )
282+
283+ // The failing probe must not prevent the surrounding probes from being registered.
284+ expect ( getProbes ( 'test.js;before' ) ) . toBeDefined ( )
285+ expect ( getProbes ( 'test.js;after' ) ) . toBeDefined ( )
286+ expect ( getProbes ( 'test.js;invalid' ) ) . toBeUndefined ( )
287+ expect ( errorSpy ) . toHaveBeenCalledOnceWith ( 'Failed to add probe invalid:' , jasmine . any ( Error ) )
288+ } )
289+
290+ it ( 'should not track a probe that failed to initialize, so a later deletion is a no-op' , async ( ) => {
291+ respondWith ( {
292+ nextCursor : 'cursor-1' ,
293+ updates : [
294+ createProbe ( {
295+ id : 'invalid' ,
296+ captureSnapshot : false ,
297+ captureExpressions : [
298+ {
299+ name : 'invalid expr' ,
300+ expr : { dsl : 'not a valid identifier!' , json : { ref : 'not a valid identifier!' } } ,
301+ } ,
302+ ] ,
303+ } ) ,
304+ ] ,
305+ deletions : [ ] ,
306+ } )
307+
308+ startDeliveryApiPolling ( makeConfig ( ) )
309+ await flushPromises ( )
310+ expect ( errorSpy ) . toHaveBeenCalledOnceWith ( 'Failed to add probe invalid:' , jasmine . any ( Error ) )
311+
312+ errorSpy . calls . reset ( )
313+
314+ // The failed probe was never tracked, so deleting it does nothing and must
315+ // not attempt a removal (which would log a "Failed to remove probe" error).
316+ respondWith ( {
317+ nextCursor : 'cursor-2' ,
318+ updates : [ ] ,
319+ deletions : [ 'invalid' ] ,
320+ } )
321+ clock . tick ( 5000 )
322+ await flushPromises ( )
323+
324+ expect ( errorSpy ) . not . toHaveBeenCalled ( )
325+ } )
326+
327+ it ( 'should keep polling after a probe fails to initialize' , async ( ) => {
328+ respondWith ( {
329+ nextCursor : 'cursor-1' ,
330+ updates : [
331+ createProbe ( {
332+ id : 'invalid' ,
333+ captureSnapshot : false ,
334+ captureExpressions : [
335+ {
336+ name : 'invalid expr' ,
337+ expr : { dsl : 'not a valid identifier!' , json : { ref : 'not a valid identifier!' } } ,
338+ } ,
339+ ] ,
340+ } ) ,
341+ ] ,
342+ deletions : [ ] ,
343+ } )
344+
345+ startDeliveryApiPolling ( makeConfig ( { pollInterval : 5000 } ) )
346+ await flushPromises ( )
347+ expect ( errorSpy ) . toHaveBeenCalledOnceWith ( 'Failed to add probe invalid:' , jasmine . any ( Error ) )
348+
349+ // A per-probe compilation error is a data error, not a transport failure:
350+ // it must not trip the circuit breaker or stop polling.
351+ const callsBefore = fetchSpy . calls . count ( )
352+ clock . tick ( 5000 )
353+ await flushPromises ( )
354+
355+ expect ( fetchSpy . calls . count ( ) ) . toBe ( callsBefore + 1 )
356+ expect ( warnSpy ) . not . toHaveBeenCalledWith ( jasmine . stringMatching ( / c i r c u i t b r e a k e r / i) )
357+ } )
358+
259359 it ( 'should ignore log probes without a where clause' , async ( ) => {
260360 respondWith ( {
261361 nextCursor : 'cursor-1' ,
0 commit comments