shikibu 0.1.0 → 0.2.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6d241ad341f0963dd1fe64cb61dc2a25a95fd8d0f01d12aef81c0372075dbcba
4
- data.tar.gz: d287f1ee1f8f58a6a4b6f44565e54ad848792ec3005931fe77a55a187c7c7a6c
3
+ metadata.gz: 5b3b677128439973fcda2120c7377d1de6cc358bd4cd0b3fd9857e089d85de62
4
+ data.tar.gz: 6826b04fff743009f655282d55451c9850066116343c2da1211e7178d451ed6b
5
5
  SHA512:
6
- metadata.gz: 39e4b6bbabb954eb6fd11ec715e91afff3b61ba2737c836332ed5161b6f5f9cbef2d30b72f3b08b96d76b96e05018e86127c88fffb8952a0aece2724e643a979
7
- data.tar.gz: bc4cacdb7f83dc73a80468d0daa92af3bc23f69315b07836e12d195b48d46c4bbe5ed18374609cefe7fc8ba03cd3fde8fff9316b147646b85ff57bad99d637df
6
+ metadata.gz: 3d7c8eb5b7c2722cbb6569659c61fc02540ba5ef9d9d9da55281e9b482e0ff0a567b4434f309010d3faa35aed0ebd6592a97b77826410db3476a34dd80ea4d8b
7
+ data.tar.gz: 842f548cc2394a5a4a0aeb1641812c6e26f9e24d3f9f73bfeba6d262e3598429e102b560069897a75a6ea0ea9319c4fa27b67689c00714e5d6be3a5ccf6156e2
@@ -33,8 +33,43 @@ module Shikibu
33
33
  # Transaction Management
34
34
  # ============================================
35
35
 
36
+ # Thread-local storage for transaction state
37
+ # Tracks nesting depth and post-commit callbacks
38
+ def transaction_state
39
+ Thread.current[:shikibu_tx_state] ||= { depth: 0, callbacks: [] }
40
+ end
41
+
42
+ # Register a callback to be executed after successful commit of the outermost transaction
43
+ # @param block [Proc] The callback to execute after commit
44
+ # @raise [RuntimeError] If called outside of a transaction
45
+ def register_post_commit_callback(&block)
46
+ raise 'Not in transaction' unless in_transaction?
47
+
48
+ transaction_state[:callbacks] << block
49
+ end
50
+
36
51
  def transaction(&)
37
- @db.transaction(&)
52
+ state = transaction_state
53
+ state[:depth] += 1
54
+ committed = false
55
+
56
+ begin
57
+ result = @db.transaction(&)
58
+ committed = true
59
+
60
+ # Execute callbacks only after successful commit of outermost transaction
61
+ if state[:depth] == 1
62
+ callbacks = state[:callbacks].dup
63
+ state[:callbacks].clear
64
+ callbacks.each(&:call)
65
+ end
66
+
67
+ result
68
+ ensure
69
+ state[:depth] -= 1
70
+ # Clear callbacks on rollback (when not committed) at outermost level
71
+ state[:callbacks].clear if state[:depth].zero? && !committed
72
+ end
38
73
  end
39
74
 
40
75
  def in_transaction?
@@ -405,8 +440,15 @@ module Shikibu
405
440
  )
406
441
  end
407
442
 
408
- # Send NOTIFY for new message
409
- send_notify(Notify::Channel::CHANNEL_MESSAGE, { ch: channel, msg_id: message_id })
443
+ # Send NOTIFY for new message (deferred if in transaction)
444
+ notify_payload = { ch: channel, msg_id: message_id }
445
+ if in_transaction?
446
+ register_post_commit_callback do
447
+ send_notify(Notify::Channel::CHANNEL_MESSAGE, notify_payload)
448
+ end
449
+ else
450
+ send_notify(Notify::Channel::CHANNEL_MESSAGE, notify_payload)
451
+ end
410
452
 
411
453
  message_id
412
454
  end
@@ -588,8 +630,15 @@ module Shikibu
588
630
  )
589
631
  end
590
632
 
591
- # Send NOTIFY for new outbox event
592
- send_notify(Notify::Channel::OUTBOX_PENDING, { evt_id: event_id, evt_type: event_type })
633
+ # Send NOTIFY for new outbox event (deferred if in transaction)
634
+ notify_payload = { evt_id: event_id, evt_type: event_type }
635
+ if in_transaction?
636
+ register_post_commit_callback do
637
+ send_notify(Notify::Channel::OUTBOX_PENDING, notify_payload)
638
+ end
639
+ else
640
+ send_notify(Notify::Channel::OUTBOX_PENDING, notify_payload)
641
+ end
593
642
  end
594
643
 
595
644
  def get_pending_outbox_events(limit: 100)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Shikibu
4
- VERSION = '0.1.0'
4
+ VERSION = '0.2.0'
5
5
  end
@@ -279,21 +279,24 @@ module Shikibu
279
279
  end
280
280
 
281
281
  def execute_single_compensation(comp, compensation_id)
282
- comp[:block].call
283
-
284
- # Record successful compensation (Romancy/Edda compatible format)
285
- ctx.storage.append_history(
286
- instance_id: ctx.instance_id,
287
- activity_id: "compensation:#{compensation_id || comp[:activity_id]}",
288
- event_type: EventType::COMPENSATION_EXECUTED,
289
- event_data: {
290
- compensation_id: compensation_id,
291
- activity_id: comp[:activity_id],
292
- activity_name: comp[:compensation_name]
293
- }
294
- )
282
+ # Execute compensation and record result atomically in a transaction
283
+ ctx.storage.transaction do
284
+ comp[:block].call
285
+
286
+ # Record successful compensation (Romancy/Edda compatible format)
287
+ ctx.storage.append_history(
288
+ instance_id: ctx.instance_id,
289
+ activity_id: "compensation:#{compensation_id || comp[:activity_id]}",
290
+ event_type: EventType::COMPENSATION_EXECUTED,
291
+ event_data: {
292
+ compensation_id: compensation_id,
293
+ activity_id: comp[:activity_id],
294
+ activity_name: comp[:compensation_name]
295
+ }
296
+ )
297
+ end
295
298
  rescue StandardError => e
296
- # Record failed compensation but continue with others
299
+ # Record failed compensation but continue with others (outside transaction)
297
300
  ctx.storage.append_history(
298
301
  instance_id: ctx.instance_id,
299
302
  activity_id: "compensation:#{compensation_id || comp[:activity_id]}",
@@ -320,23 +323,28 @@ module Shikibu
320
323
  # Call hooks
321
324
  ctx.hooks&.on_activity_start&.call(ctx.instance_id, activity_id, name, attempt)
322
325
 
323
- result = block.call
326
+ # Execute activity and record result atomically in a transaction
327
+ result = ctx.storage.transaction do
328
+ res = block.call
329
+
330
+ # Record successful result (atomic with activity execution)
331
+ ctx.storage.append_history(
332
+ instance_id: ctx.instance_id,
333
+ activity_id: activity_id,
334
+ event_type: EventType::ACTIVITY_COMPLETED,
335
+ event_data: { result: res }
336
+ )
324
337
 
325
- # Record successful result
326
- ctx.storage.append_history(
327
- instance_id: ctx.instance_id,
328
- activity_id: activity_id,
329
- event_type: EventType::ACTIVITY_COMPLETED,
330
- event_data: { result: result }
331
- )
338
+ res
339
+ end
332
340
 
333
- # Cache for replay
341
+ # Cache for replay (outside transaction)
334
342
  ctx.cache_result(activity_id, {
335
343
  event_type: EventType::ACTIVITY_COMPLETED,
336
344
  result: result
337
345
  })
338
346
 
339
- # Call hooks
347
+ # Call hooks (outside transaction)
340
348
  ctx.hooks&.on_activity_complete&.call(ctx.instance_id, activity_id, name, result, false)
341
349
 
342
350
  return result
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: shikibu
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yasushi Itoh