appsignal 4.0.2-java → 4.0.4-java

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.
@@ -0,0 +1,210 @@
1
+ describe Appsignal::CheckIn::Cron do
2
+ let(:config) { project_fixture_config }
3
+ let(:cron_checkin) { described_class.new(:identifier => "cron-checkin-name") }
4
+ let(:transmitter) { Appsignal::Transmitter.new("https://checkin-endpoint.invalid") }
5
+ let(:scheduler) { Appsignal::CheckIn::Scheduler.new }
6
+
7
+ before do
8
+ allow(Appsignal).to receive(:active?).and_return(true)
9
+ config.logger = Logger.new(StringIO.new)
10
+ allow(Appsignal::CheckIn).to receive(:scheduler).and_return(scheduler)
11
+ allow(Appsignal::CheckIn).to receive(:transmitter).and_return(transmitter)
12
+ end
13
+
14
+ after do
15
+ scheduler.stop
16
+ end
17
+
18
+ describe "when Appsignal is not active" do
19
+ it "should not transmit any events" do
20
+ allow(Appsignal).to receive(:active?).and_return(false)
21
+
22
+ expect(Appsignal.internal_logger).to receive(:debug).with(satisfy do |message|
23
+ message.include?("Cannot transmit cron check-in `cron-checkin-name` start event") &&
24
+ message.include?("AppSignal is not active")
25
+ end)
26
+
27
+ cron_checkin.start
28
+
29
+ expect(Appsignal.internal_logger).to receive(:debug).with(satisfy do |message|
30
+ message.include?("Cannot transmit cron check-in `cron-checkin-name` finish event") &&
31
+ message.include?("AppSignal is not active")
32
+ end)
33
+
34
+ cron_checkin.finish
35
+
36
+ expect(transmitter).not_to receive(:transmit)
37
+
38
+ scheduler.stop
39
+ end
40
+ end
41
+
42
+ describe "when AppSignal is stopped" do
43
+ it "should not transmit any events" do
44
+ expect(transmitter).not_to receive(:transmit)
45
+
46
+ expect(Appsignal.internal_logger).to receive(:debug).with("Stopping AppSignal")
47
+
48
+ Appsignal.stop
49
+
50
+ expect(Appsignal.internal_logger).to receive(:debug).with(satisfy do |message|
51
+ message.include?("Cannot transmit cron check-in `cron-checkin-name` start event") &&
52
+ message.include?("AppSignal is stopped")
53
+ end)
54
+
55
+ cron_checkin.start
56
+
57
+ expect(Appsignal.internal_logger).to receive(:debug).with(satisfy do |message|
58
+ message.include?("Cannot transmit cron check-in `cron-checkin-name` finish event") &&
59
+ message.include?("AppSignal is stopped")
60
+ end)
61
+
62
+ cron_checkin.finish
63
+
64
+ expect(Appsignal.internal_logger).to receive(:debug).with("Stopping AppSignal")
65
+
66
+ Appsignal.stop
67
+ end
68
+ end
69
+
70
+ describe "#start" do
71
+ it "should send a cron check-in start" do
72
+ expect(Appsignal.internal_logger).not_to receive(:error)
73
+
74
+ expect(Appsignal.internal_logger).to receive(:debug).with(satisfy do |message|
75
+ message.include?("Scheduling cron check-in `cron-checkin-name` start event")
76
+ end)
77
+
78
+ cron_checkin.start
79
+
80
+ expect(Appsignal.internal_logger).to receive(:debug).with(satisfy do |message|
81
+ message.include?("Transmitted cron check-in `cron-checkin-name` start event")
82
+ end)
83
+
84
+ expect(transmitter).to receive(:transmit).with([hash_including(
85
+ :identifier => "cron-checkin-name",
86
+ :kind => "start",
87
+ :check_in_type => "cron"
88
+ )], :format => :ndjson).and_return(Net::HTTPResponse.new(nil, "200", nil))
89
+
90
+ scheduler.stop
91
+ end
92
+
93
+ it "should log an error if it fails" do
94
+ expect(Appsignal.internal_logger).to receive(:debug).with(satisfy do |message|
95
+ message.include?("Scheduling cron check-in `cron-checkin-name` start event")
96
+ end)
97
+
98
+ cron_checkin.start
99
+
100
+ expect(Appsignal.internal_logger).to receive(:error).with(satisfy do |message|
101
+ message.include?("Failed to transmit cron check-in `cron-checkin-name` start event") &&
102
+ message.include?("499 status code")
103
+ end)
104
+
105
+ expect(transmitter).to receive(:transmit).with([hash_including(
106
+ :identifier => "cron-checkin-name",
107
+ :kind => "start",
108
+ :check_in_type => "cron"
109
+ )], :format => :ndjson).and_return(Net::HTTPResponse.new(nil, "499", nil))
110
+
111
+ scheduler.stop
112
+ end
113
+ end
114
+
115
+ describe "#finish" do
116
+ it "should send a cron check-in finish" do
117
+ expect(Appsignal.internal_logger).not_to receive(:error)
118
+
119
+ expect(Appsignal.internal_logger).to receive(:debug).with(satisfy do |message|
120
+ message.include?("Scheduling cron check-in `cron-checkin-name` finish event")
121
+ end)
122
+
123
+ cron_checkin.finish
124
+
125
+ expect(Appsignal.internal_logger).to receive(:debug).with(satisfy do |message|
126
+ message.include?("Transmitted cron check-in `cron-checkin-name` finish event")
127
+ end)
128
+
129
+ expect(transmitter).to receive(:transmit).with([hash_including(
130
+ :identifier => "cron-checkin-name",
131
+ :kind => "finish",
132
+ :check_in_type => "cron"
133
+ )], :format => :ndjson).and_return(Net::HTTPResponse.new(nil, "200", nil))
134
+
135
+ scheduler.stop
136
+ end
137
+
138
+ it "should log an error if it fails" do
139
+ expect(Appsignal.internal_logger).to receive(:debug).with(satisfy do |message|
140
+ message.include?("Scheduling cron check-in `cron-checkin-name` finish event")
141
+ end)
142
+
143
+ cron_checkin.finish
144
+
145
+ expect(Appsignal.internal_logger).to receive(:error).with(satisfy do |message|
146
+ message.include?("Failed to transmit cron check-in `cron-checkin-name` finish event") &&
147
+ message.include?("499 status code")
148
+ end)
149
+
150
+ expect(transmitter).to receive(:transmit).with([hash_including(
151
+ :identifier => "cron-checkin-name",
152
+ :kind => "finish",
153
+ :check_in_type => "cron"
154
+ )], :format => :ndjson).and_return(Net::HTTPResponse.new(nil, "499", nil))
155
+
156
+ scheduler.stop
157
+ end
158
+ end
159
+
160
+ describe ".cron" do
161
+ describe "when a block is given" do
162
+ it "should send a cron check-in start and finish and return the block output" do
163
+ expect(scheduler).to receive(:schedule).with(hash_including(
164
+ :kind => "start",
165
+ :identifier => "cron-checkin-with-block",
166
+ :check_in_type => "cron"
167
+ ))
168
+
169
+ expect(scheduler).to receive(:schedule).with(hash_including(
170
+ :kind => "finish",
171
+ :identifier => "cron-checkin-with-block",
172
+ :check_in_type => "cron"
173
+ ))
174
+
175
+ output = Appsignal::CheckIn.cron("cron-checkin-with-block") { "output" }
176
+ expect(output).to eq("output")
177
+ end
178
+
179
+ it "should not send a cron check-in finish event when an error is raised" do
180
+ expect(scheduler).to receive(:schedule).with(hash_including(
181
+ :kind => "start",
182
+ :identifier => "cron-checkin-with-block",
183
+ :check_in_type => "cron"
184
+ ))
185
+
186
+ expect(scheduler).not_to receive(:schedule).with(hash_including(
187
+ :kind => "finish",
188
+ :identifier => "cron-checkin-with-block",
189
+ :check_in_type => "cron"
190
+ ))
191
+
192
+ expect do
193
+ Appsignal::CheckIn.cron("cron-checkin-with-block") { raise "error" }
194
+ end.to raise_error(RuntimeError, "error")
195
+ end
196
+ end
197
+
198
+ describe "when no block is given" do
199
+ it "should only send a cron check-in finish event" do
200
+ expect(scheduler).to receive(:schedule).with(hash_including(
201
+ :kind => "finish",
202
+ :identifier => "cron-checkin-without-block",
203
+ :check_in_type => "cron"
204
+ ))
205
+
206
+ Appsignal::CheckIn.cron("cron-checkin-without-block")
207
+ end
208
+ end
209
+ end
210
+ end
@@ -0,0 +1,484 @@
1
+ describe Appsignal::CheckIn::Scheduler do
2
+ include WaitForHelper
3
+ include TakeAtMostHelper
4
+
5
+ let(:transmitter) { Appsignal::Transmitter.new("http://checkin-endpoint.invalid") }
6
+
7
+ before do
8
+ allow(Appsignal).to receive(:active?).and_return(true)
9
+ allow(transmitter).to receive(:transmit).and_return(Net::HTTPSuccess.new("1.1", 200, "OK"))
10
+ allow(Appsignal::CheckIn).to receive(:transmitter).and_return(transmitter)
11
+ allow(Appsignal::CheckIn).to receive(:scheduler).and_return(subject)
12
+ # Shorten debounce intervals to make the tests run faster.
13
+ stub_const("Appsignal::CheckIn::Scheduler::INITIAL_DEBOUNCE_SECONDS", 0.1)
14
+ stub_const("Appsignal::CheckIn::Scheduler::BETWEEN_TRANSMISSIONS_DEBOUNCE_SECONDS", 0.1)
15
+ end
16
+
17
+ after do
18
+ subject.stop
19
+ end
20
+
21
+ describe "when no event is sent" do
22
+ it "does not start a thread" do
23
+ expect(subject.thread).to be_nil
24
+ end
25
+
26
+ it "does not schedule a debounce" do
27
+ expect(subject.waker).to be_nil
28
+ end
29
+
30
+ it "can be stopped" do
31
+ # Set all debounce intervals to 10 seconds, to make the assertion
32
+ # fail if it waits for the debounce -- this ensures that what is being
33
+ # tested is that no debounces are awaited when stopping the scheduler.
34
+ stub_const("Appsignal::CheckIn::Scheduler::INITIAL_DEBOUNCE_SECONDS", 10)
35
+ stub_const("Appsignal::CheckIn::Scheduler::BETWEEN_TRANSMISSIONS_DEBOUNCE_SECONDS", 10)
36
+
37
+ take_at_most(0.1) do
38
+ expect { subject.stop }.not_to raise_error
39
+ end
40
+ end
41
+
42
+ it "can be stopped more than once" do
43
+ # Set all debounce intervals to 10 seconds, to make the assertion
44
+ # fail if it waits for the debounce -- this ensures that what is being
45
+ # tested is that no debounces are awaited when stopping the scheduler.
46
+ stub_const("Appsignal::CheckIn::Scheduler::INITIAL_DEBOUNCE_SECONDS", 10)
47
+ stub_const("Appsignal::CheckIn::Scheduler::BETWEEN_TRANSMISSIONS_DEBOUNCE_SECONDS", 10)
48
+
49
+ take_at_most(0.1) do
50
+ expect { subject.stop }.not_to raise_error
51
+ expect { subject.stop }.not_to raise_error
52
+ end
53
+ end
54
+
55
+ it "closes the queue when stopped" do
56
+ subject.stop
57
+ expect(subject.queue.closed?).to be(true)
58
+ end
59
+ end
60
+
61
+ describe "when an event is sent" do
62
+ it "starts a thread" do
63
+ Appsignal::CheckIn.cron("test")
64
+ expect(subject.thread).to be_a(Thread)
65
+ end
66
+
67
+ it "schedules a debounce" do
68
+ Appsignal::CheckIn.cron("test")
69
+ expect(subject.waker).to be_a(Thread)
70
+ end
71
+
72
+ it "schedules the event to be transmitted" do
73
+ expect(transmitter).to receive(:transmit).with([hash_including(
74
+ :identifier => "test",
75
+ :check_in_type => "cron",
76
+ :kind => "finish"
77
+ )], :format => :ndjson)
78
+
79
+ expect(Appsignal.internal_logger).to receive(:debug).with(satisfy do |message|
80
+ message.include?("Scheduling cron check-in `test` finish event")
81
+ end)
82
+
83
+ expect(subject.events).to be_empty
84
+
85
+ Appsignal::CheckIn.cron("test")
86
+
87
+ expect(subject.events).not_to be_empty
88
+
89
+ expect(Appsignal.internal_logger).to receive(:debug).with(satisfy do |message|
90
+ message.include?("Transmitted cron check-in `test` finish event")
91
+ end)
92
+
93
+ wait_for("the event to be transmitted") { subject.transmitted == 1 }
94
+
95
+ expect(subject.events).to be_empty
96
+ end
97
+
98
+ it "waits for the event to be transmitted when stopped" do
99
+ # Set all debounce intervals to 10 seconds, to make the test
100
+ # fail if it waits for the debounce -- this ensures that what is being
101
+ # tested is that the events are transmitted immediately when the
102
+ # scheduler is stopped, without waiting for any debounce.
103
+ stub_const("Appsignal::CheckIn::Scheduler::INITIAL_DEBOUNCE_SECONDS", 10)
104
+ stub_const("Appsignal::CheckIn::Scheduler::BETWEEN_TRANSMISSIONS_DEBOUNCE_SECONDS", 10)
105
+
106
+ expect(transmitter).to receive(:transmit).with([hash_including(
107
+ :identifier => "test",
108
+ :check_in_type => "cron",
109
+ :kind => "finish"
110
+ )], :format => :ndjson)
111
+
112
+ expect(Appsignal.internal_logger).to receive(:debug).with(satisfy do |message|
113
+ message.include?("Scheduling cron check-in `test` finish event")
114
+ end)
115
+
116
+ Appsignal::CheckIn.cron("test")
117
+
118
+ expect(Appsignal.internal_logger).to receive(:debug).with(satisfy do |message|
119
+ message.include?("Transmitted cron check-in `test` finish event")
120
+ end)
121
+
122
+ expect(subject.events).not_to be_empty
123
+
124
+ take_at_most(0.1) do
125
+ expect { subject.stop }.not_to raise_error
126
+ end
127
+
128
+ # Check that the thread wasn't killed before the transmission was
129
+ # completed.
130
+ expect(subject.transmitted).to eq(1)
131
+
132
+ expect(subject.events).to be_empty
133
+ end
134
+
135
+ it "can be stopped more than once" do
136
+ # Set all debounce intervals to 10 seconds, to make the test
137
+ # fail if it waits for the debounce -- this ensures that what is being
138
+ # tested is that the events are transmitted immediately when the
139
+ # scheduler is stopped, without waiting for the debounce interval.
140
+ stub_const("Appsignal::CheckIn::Scheduler::INITIAL_DEBOUNCE_SECONDS", 10)
141
+ stub_const("Appsignal::CheckIn::Scheduler::BETWEEN_TRANSMISSIONS_DEBOUNCE_SECONDS", 10)
142
+
143
+ Appsignal::CheckIn.cron("test")
144
+ take_at_most(0.1) do
145
+ expect { subject.stop }.not_to raise_error
146
+ end
147
+
148
+ # Check that the thread wasn't killed before the transmission was
149
+ # completed.
150
+ expect(subject.transmitted).to eq(1)
151
+
152
+ take_at_most(0.1) do
153
+ expect { subject.stop }.not_to raise_error
154
+ end
155
+ end
156
+
157
+ it "closes the queue when stopped" do
158
+ Appsignal::CheckIn.cron("test")
159
+ subject.stop
160
+ expect(subject.queue.closed?).to be(true)
161
+ end
162
+
163
+ it "kills the thread when stopped" do
164
+ Appsignal::CheckIn.cron("test")
165
+ subject.stop
166
+ expect(subject.thread.alive?).to be(false)
167
+ end
168
+
169
+ it "unschedules the debounce when stopped" do
170
+ Appsignal::CheckIn.cron("test")
171
+ waker = subject.waker
172
+ subject.stop
173
+ expect(waker.alive?).to be(false)
174
+ expect(subject.waker).to be_nil
175
+ end
176
+ end
177
+
178
+ describe "when many events are sent" do
179
+ describe "within the short debounce interval" do
180
+ it "transmits all events at once" do
181
+ expect(transmitter).to receive(:transmit).with(
182
+ ["first", "second", "third"].map do |identifier|
183
+ hash_including(
184
+ :identifier => identifier,
185
+ :check_in_type => "cron",
186
+ :kind => "finish"
187
+ )
188
+ end, :format => :ndjson
189
+ )
190
+
191
+ Appsignal::CheckIn.cron("first")
192
+ Appsignal::CheckIn.cron("second")
193
+ Appsignal::CheckIn.cron("third")
194
+
195
+ wait_for("the events to be transmitted") { subject.transmitted == 1 }
196
+ end
197
+
198
+ it "transmits all events at once when stopped" do
199
+ # Set a short debounce interval of 10 seconds, to make the final wait
200
+ # fail if it waits for the debounce -- this ensures that what is being
201
+ # tested is that the events are transmitted when the scheduler is
202
+ # stopped.
203
+ stub_const("Appsignal::CheckIn::Scheduler::INITIAL_DEBOUNCE_SECONDS", 10)
204
+
205
+ expect(transmitter).to receive(:transmit).with(
206
+ ["first", "second", "third"].map do |identifier|
207
+ hash_including(
208
+ :identifier => identifier,
209
+ :check_in_type => "cron",
210
+ :kind => "finish"
211
+ )
212
+ end, :format => :ndjson
213
+ )
214
+
215
+ Appsignal::CheckIn.cron("first")
216
+ Appsignal::CheckIn.cron("second")
217
+ Appsignal::CheckIn.cron("third")
218
+
219
+ subject.stop
220
+
221
+ wait_for("the events to be transmitted") { subject.transmitted == 1 }
222
+ end
223
+ end
224
+
225
+ describe "further apart than the short debounce interval" do
226
+ it "transmits the first event and enqueues future events" do
227
+ expect(transmitter).to receive(:transmit).with([hash_including(
228
+ :identifier => "first",
229
+ :check_in_type => "cron",
230
+ :kind => "finish"
231
+ )], :format => :ndjson)
232
+
233
+ Appsignal::CheckIn.cron("first")
234
+
235
+ wait_for("the first event to be transmitted") { subject.transmitted == 1 }
236
+
237
+ Appsignal::CheckIn.cron("second")
238
+ Appsignal::CheckIn.cron("third")
239
+
240
+ expect(subject.events).to match(["second", "third"].map do |identifier|
241
+ hash_including({
242
+ :identifier => identifier,
243
+ :check_in_type => "cron",
244
+ :kind => "finish"
245
+ })
246
+ end)
247
+ end
248
+
249
+ it "transmits the other events after the debounce interval" do
250
+ expect(transmitter).to receive(:transmit)
251
+
252
+ expect(Appsignal.internal_logger).to receive(:debug).with(satisfy do |message|
253
+ message.include?("Scheduling cron check-in `first` finish event")
254
+ end)
255
+
256
+ Appsignal::CheckIn.cron("first")
257
+
258
+ expect(Appsignal.internal_logger).to receive(:debug).with(satisfy do |message|
259
+ message.include?("Transmitted cron check-in `first` finish event")
260
+ end)
261
+
262
+ wait_for("the first event to be transmitted") { subject.transmitted == 1 }
263
+
264
+ expect(transmitter).to receive(:transmit).with(
265
+ ["second", "third"].map do |identifier|
266
+ hash_including(
267
+ :identifier => identifier,
268
+ :check_in_type => "cron",
269
+ :kind => "finish"
270
+ )
271
+ end, :format => :ndjson
272
+ )
273
+
274
+ expect(Appsignal.internal_logger).to receive(:debug).with(satisfy do |message|
275
+ message.include?("Scheduling cron check-in `second` finish event")
276
+ end)
277
+
278
+ Appsignal::CheckIn.cron("second")
279
+
280
+ expect(Appsignal.internal_logger).to receive(:debug).with(satisfy do |message|
281
+ message.include?("Scheduling cron check-in `third` finish event")
282
+ end)
283
+
284
+ Appsignal::CheckIn.cron("third")
285
+
286
+ expect(subject.events).to_not be_empty
287
+
288
+ expect(Appsignal.internal_logger).to receive(:debug).with(
289
+ "Transmitted 2 check-in events"
290
+ )
291
+
292
+ wait_for("the other events to be transmitted") { subject.transmitted == 2 }
293
+
294
+ expect(subject.events).to be_empty
295
+ end
296
+
297
+ it "transmits the other events when stopped" do
298
+ # Restore the original long debounce interval of 10 seconds, to make
299
+ # the final wait fail if it waits for the debounce -- this ensures
300
+ # that what is being tested is that the events are transmitted
301
+ # immediately when the scheduler is stopped.
302
+ stub_const("Appsignal::CheckIn::Scheduler::BETWEEN_TRANSMISSIONS_DEBOUNCE_SECONDS", 10)
303
+
304
+ expect(transmitter).to receive(:transmit)
305
+
306
+ expect(Appsignal.internal_logger).to receive(:debug).with(satisfy do |message|
307
+ message.include?("Scheduling cron check-in `first` finish event")
308
+ end)
309
+
310
+ Appsignal::CheckIn.cron("first")
311
+
312
+ expect(Appsignal.internal_logger).to receive(:debug).with(satisfy do |message|
313
+ message.include?("Transmitted cron check-in `first` finish event")
314
+ end)
315
+
316
+ wait_for("the event to be transmitted") { subject.transmitted == 1 }
317
+
318
+ expect(transmitter).to receive(:transmit).with(
319
+ ["second", "third"].map do |identifier|
320
+ hash_including(
321
+ :identifier => identifier,
322
+ :check_in_type => "cron",
323
+ :kind => "finish"
324
+ )
325
+ end, :format => :ndjson
326
+ )
327
+
328
+ expect(Appsignal.internal_logger).to receive(:debug).with(satisfy do |message|
329
+ message.include?("Scheduling cron check-in `second` finish event")
330
+ end)
331
+
332
+ Appsignal::CheckIn.cron("second")
333
+
334
+ expect(Appsignal.internal_logger).to receive(:debug).with(satisfy do |message|
335
+ message.include?("Scheduling cron check-in `third` finish event")
336
+ end)
337
+
338
+ Appsignal::CheckIn.cron("third")
339
+
340
+ expect(subject.events).to_not be_empty
341
+
342
+ expect(Appsignal.internal_logger).to receive(:debug).with(
343
+ "Transmitted 2 check-in events"
344
+ )
345
+
346
+ subject.stop
347
+
348
+ wait_for("the other events to be transmitted") { subject.transmitted == 2 }
349
+
350
+ expect(subject.events).to be_empty
351
+ end
352
+ end
353
+ end
354
+
355
+ describe "when a similar event is sent more than once" do
356
+ it "only transmits one of the similar events" do
357
+ # We must instantiate `Appsignal::CheckIn::Cron` directly, as the
358
+ # `.cron` helper would use a different digest for each invocation.
359
+ cron = Appsignal::CheckIn::Cron.new(:identifier => "test")
360
+
361
+ expect(transmitter).to receive(:transmit).with([hash_including(
362
+ :identifier => "test",
363
+ :check_in_type => "cron",
364
+ :kind => "start"
365
+ )], :format => :ndjson)
366
+
367
+ expect(Appsignal.internal_logger).to receive(:debug).with(
368
+ "Scheduling cron check-in `test` start event (digest #{cron.digest}) to be transmitted"
369
+ )
370
+
371
+ cron.start
372
+
373
+ expect(Appsignal.internal_logger).to receive(:debug).with(
374
+ "Scheduling cron check-in `test` start event (digest #{cron.digest}) to be transmitted"
375
+ )
376
+
377
+ expect(Appsignal.internal_logger).to receive(:debug).with(
378
+ "Replacing previously scheduled cron check-in `test` start event (digest #{cron.digest})"
379
+ )
380
+
381
+ cron.start
382
+
383
+ expect(Appsignal.internal_logger).to receive(:debug).with(
384
+ "Transmitted cron check-in `test` start event (digest #{cron.digest})"
385
+ )
386
+
387
+ wait_for("the event to be transmitted") { subject.transmitted == 1 }
388
+ end
389
+ end
390
+
391
+ describe "when the scheduler is stopped" do
392
+ it "does not schedule any events to be transmitted" do
393
+ expect(transmitter).not_to receive(:transmit)
394
+
395
+ subject.stop
396
+
397
+ expect(Appsignal.internal_logger).to receive(:debug).with(satisfy do |message|
398
+ message.include?("Cannot transmit cron check-in `test` finish event") &&
399
+ message.include?("AppSignal is stopped")
400
+ end)
401
+
402
+ Appsignal::CheckIn.cron("test")
403
+
404
+ expect(subject.events).to be_empty
405
+ end
406
+ end
407
+
408
+ describe "when AppSignal is not active" do
409
+ it "does not schedule any events to be transmitted" do
410
+ allow(Appsignal).to receive(:active?).and_return(false)
411
+
412
+ subject.stop
413
+
414
+ expect(Appsignal.internal_logger).to receive(:debug).with(satisfy do |message|
415
+ message.include?("Cannot transmit cron check-in `test` finish event") &&
416
+ message.include?("AppSignal is not active")
417
+ end)
418
+
419
+ Appsignal::CheckIn.cron("test")
420
+
421
+ expect(subject.events).to be_empty
422
+ end
423
+ end
424
+
425
+ describe "when transmitting returns a non-success response code" do
426
+ it "logs the error and continues" do
427
+ expect(transmitter).to receive(:transmit).and_return(
428
+ Net::HTTPNotFound.new("1.1", 404, "Not Found")
429
+ )
430
+
431
+ Appsignal::CheckIn.cron("first")
432
+
433
+ expect(Appsignal.internal_logger).to receive(:error).with(satisfy do |message|
434
+ message.include?("Failed to transmit cron check-in `first` finish event") &&
435
+ message.include?("404 status code")
436
+ end)
437
+
438
+ wait_for("the first event to be transmitted") { subject.transmitted == 1 }
439
+
440
+ expect(transmitter).to receive(:transmit).and_return(
441
+ Net::HTTPSuccess.new("1.1", 200, "OK")
442
+ )
443
+
444
+ Appsignal::CheckIn.cron("second")
445
+
446
+ expect(Appsignal.internal_logger).not_to receive(:error)
447
+
448
+ expect(Appsignal.internal_logger).to receive(:debug).with(satisfy do |message|
449
+ message.include?("Transmitted cron check-in `second` finish event")
450
+ end)
451
+
452
+ wait_for("the second event to be transmitted") { subject.transmitted == 2 }
453
+ end
454
+ end
455
+
456
+ describe "when transmitting throws an error" do
457
+ it "logs the error and continues" do
458
+ expect(transmitter).to receive(:transmit).and_raise("Something went wrong")
459
+
460
+ Appsignal::CheckIn.cron("first")
461
+
462
+ expect(Appsignal.internal_logger).to receive(:error).with(satisfy do |message|
463
+ message.include?("Failed to transmit cron check-in `first` finish event") &&
464
+ message.include?("Something went wrong")
465
+ end)
466
+
467
+ wait_for("the first event to be transmitted") { subject.transmitted == 1 }
468
+
469
+ expect(transmitter).to receive(:transmit).and_return(
470
+ Net::HTTPSuccess.new("1.1", 200, "OK")
471
+ )
472
+
473
+ Appsignal::CheckIn.cron("second")
474
+
475
+ expect(Appsignal.internal_logger).not_to receive(:error)
476
+
477
+ expect(Appsignal.internal_logger).to receive(:debug).with(satisfy do |message|
478
+ message.include?("Transmitted cron check-in `second` finish event")
479
+ end)
480
+
481
+ wait_for("the second event to be transmitted") { subject.transmitted == 2 }
482
+ end
483
+ end
484
+ end