cdc-parallel 0.2.2 → 0.2.3

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.
data/lib/cdc/parallel.rb CHANGED
@@ -13,7 +13,39 @@ require_relative "parallel/router"
13
13
  require_relative "parallel/runtime"
14
14
 
15
15
  module CDC
16
- # Optional parallel Change Data Capture runtime for cdc-core processors.
16
+ # Optional parallel Change Data Capture runtime for `cdc-core` processors.
17
+ #
18
+ # `CDC::Parallel` is the CPU-bound execution layer of the CDC Ecosystem. It
19
+ # consumes work items that have already been normalized into `cdc-core`
20
+ # vocabulary objects and executes Ractor-safe processors across pre-warmed
21
+ # worker Ractors.
22
+ #
23
+ # The namespace intentionally avoids `CDC::Ractor` so it does not collide with
24
+ # Ruby's core `::Ractor` constant.
25
+ #
26
+ # ## Boundary
27
+ #
28
+ # `cdc-parallel` does not connect to PostgreSQL, parse `pgoutput`, decode
29
+ # values, normalize source payloads, or persist sink data. Those concerns live
30
+ # upstream in `pgoutput-*` libraries, source adapters, and downstream sinks.
31
+ #
32
+ # ## Main entry points
33
+ #
34
+ # * {CDC::Parallel::Runtime} - high-level facade for events and transactions
35
+ # * {CDC::Parallel::ProcessorPool} - low-level Ractor worker pool
36
+ # * {CDC::Parallel::TransactionPool} - transaction-envelope wrapper
37
+ # * {CDC::Parallel::Router} - work item router
38
+ #
39
+ # @example
40
+ # runtime = CDC::Parallel::Runtime.new(
41
+ # processor: AnalyticsProcessor.new,
42
+ # size: 4
43
+ # )
44
+ #
45
+ # result = runtime.process(change_event)
46
+ # runtime.shutdown
47
+ #
48
+ # @api public
17
49
  module Parallel
18
50
  end
19
51
  end
@@ -1,8 +1,14 @@
1
1
  module CDC
2
2
  module Parallel
3
3
  # Immutable configuration for Ractor runtimes.
4
- class Configuration
5
- def initialize: (?size: untyped, ?timeout: untyped?) -> void
4
+ class Configuration < Data
5
+ attr_reader size: Integer
6
+
7
+ attr_reader timeout: Numeric?
8
+
9
+ def self.new: (?size: Integer, ?timeout: Numeric?) -> instance
10
+
11
+ def initialize: (?size: Integer, ?timeout: Numeric?) -> void
6
12
  end
7
13
  end
8
14
  end
@@ -18,19 +18,19 @@ module CDC
18
18
 
19
19
  # Raised when processor execution fails inside a worker Ractor.
20
20
  class ProcessorExecutionError < Error
21
- @original_class: untyped
21
+ @original_class: String
22
22
 
23
- @original_message: untyped
23
+ @original_message: String
24
24
 
25
- @original_backtrace: untyped
25
+ @original_backtrace: Array[String]
26
26
 
27
- attr_reader original_class: untyped
27
+ attr_reader original_class: String
28
28
 
29
- attr_reader original_message: untyped
29
+ attr_reader original_message: String
30
30
 
31
- attr_reader original_backtrace: untyped
31
+ attr_reader original_backtrace: Array[String]
32
32
 
33
- def initialize: (original_class: untyped, original_message: untyped, ?original_backtrace: untyped) -> void
33
+ def initialize: (original_class: String?, original_message: String, ?original_backtrace: Array[String]) -> void
34
34
  end
35
35
 
36
36
  # Raised when a worker does not return a result before timeout.
@@ -2,60 +2,77 @@ module CDC
2
2
  module Parallel
3
3
  # Executes one Ractor-safe processor in pre-warmed persistent Ractor workers.
4
4
  class ProcessorPool
5
- @processor: untyped
5
+ type work_item = untyped
6
+ type result = CDC::Core::ProcessorResult
7
+ type worker_response = result | Hash[Symbol, untyped] | untyped
8
+ type reply_port = Ractor::Port
9
+ type worker_inbox = Ractor::Port
10
+ @processor: CDC::Core::Processor
6
11
 
7
- @configuration: untyped
12
+ @configuration: Configuration
8
13
 
9
- @workers: untyped
14
+ @workers: Array[Ractor]
15
+
16
+ @worker_inboxes: Array[worker_inbox]
10
17
 
11
18
  @next_worker: Integer
12
19
 
13
- @shutdown: untyped
20
+ @dispatch_mutex: Mutex
21
+
22
+ @shutdown: bool
14
23
 
15
24
  # @param processor [CDC::Core::Processor]
16
25
  # @param size [Integer]
17
26
  # @param timeout [Float, nil]
18
27
  # @return [void]
19
- def initialize: (processor: untyped, ?size: untyped, ?timeout: untyped?) -> void
28
+ def initialize: (processor: CDC::Core::Processor, ?size: Integer, ?timeout: Numeric?) -> void
20
29
 
21
30
  # Process one work item synchronously.
22
31
  #
23
32
  # @param item [Object]
24
33
  # @return [CDC::Core::ProcessorResult]
25
- def process: (untyped item) -> untyped
34
+ def process: (work_item item) -> result
26
35
 
27
36
  # Process many work items using the pre-warmed worker pool.
28
37
  #
29
38
  # @param items [Array<Object>]
30
39
  # @return [Array<CDC::Core::ProcessorResult>]
31
- def process_many: (untyped items) -> untyped
40
+ def process_many: (Array[work_item] items) -> Array[result]
32
41
 
33
42
  # Shut down the pool.
34
43
  #
35
44
  # @return [void]
36
- def shutdown: () -> untyped
45
+ def shutdown: () -> nil?
37
46
 
38
47
  private
39
48
 
40
- def signal_workers: () -> untyped
49
+ def self.run_worker_loop: (untyped safe_processor, untyped inbox) -> nil
50
+
51
+ def self.worker_response: (untyped safe_processor, work_item item) -> worker_response
52
+
53
+ def dispatch: (Array[work_item] work_items, reply_port reply_port) -> Array[work_item]
54
+
55
+ def signal_workers: () -> Array[worker_inbox]
41
56
 
42
57
  def wait_for_workers: () -> untyped
43
58
 
44
59
  def wait_for_workers_with_timeout: () -> untyped
45
60
 
46
- def validate_processor!: (untyped processor) -> (nil | untyped)
61
+ def validate_processor!: (CDC::Core::Processor processor) -> nil
62
+
63
+ def build_worker: (CDC::Core::Processor processor) -> ([Ractor, worker_inbox] | Array[untyped])
47
64
 
48
- def build_worker: (untyped processor) -> untyped
65
+ def start_worker: (CDC::Core::Processor processor, Ractor::Port boot_port) -> Ractor
49
66
 
50
- def next_worker: () -> untyped
67
+ def next_worker_inbox: () -> worker_inbox
51
68
 
52
- def collect_results: (untyped reply_port, Integer count) -> untyped
69
+ def collect_results: (reply_port reply_port, Integer count) -> Array[result]
53
70
 
54
- def collect_results_without_timeout: (untyped reply_port, untyped results) -> untyped
71
+ def collect_results_without_timeout: (reply_port reply_port, Array[result?] results) -> untyped
55
72
 
56
- def collect_results_with_timeout: (untyped reply_port, untyped results) -> untyped
73
+ def collect_results_with_timeout: (reply_port reply_port, Array[result?] results) -> untyped
57
74
 
58
- def timeout_results: (untyped results) -> untyped
75
+ def timeout_results: (Array[result?] results) -> Array[result]
59
76
  end
60
77
  end
61
78
  end
@@ -4,25 +4,27 @@ module CDC
4
4
  class ResultCollector
5
5
  FAILURE_MARKER: :__cdc_parallel_failure__
6
6
 
7
+ type failure_payload = Hash[Symbol, :__cdc_parallel_failure__ | String | Array[String] | nil]
8
+
7
9
  # Build a shareable success payload that can safely cross a Ractor boundary.
8
10
  #
9
11
  # @param value [Object]
10
12
  # @return [Object]
11
- def self.worker_success: (untyped value) -> untyped
13
+ def self.worker_success: [T] (T value) -> T
12
14
 
13
15
  # Build a shareable failure payload that can safely cross a Ractor boundary.
14
16
  #
15
17
  # @param error [Exception]
16
18
  # @return [Hash]
17
- def self.worker_failure: (untyped error) -> untyped
19
+ def self.worker_failure: (Exception error) -> failure_payload
18
20
 
19
21
  # Normalize a worker return value into a ProcessorResult.
20
22
  #
21
23
  # @param value [Object]
22
24
  # @return [CDC::Core::ProcessorResult]
23
- def self.normalize: (untyped value) -> untyped
25
+ def self.normalize: (CDC::Core::ProcessorResult | failure_payload | untyped value) -> CDC::Core::ProcessorResult
24
26
 
25
- def self.worker_failure?: (untyped value) -> untyped
27
+ def self.worker_failure?: (untyped value) -> bool
26
28
  end
27
29
  end
28
30
  end
@@ -2,19 +2,22 @@ module CDC
2
2
  module Parallel
3
3
  # Routes supported CDC objects to the correct runtime pool.
4
4
  class Router
5
- @processor_pool: untyped
5
+ type work_item = CDC::Core::ChangeEvent | CDC::Core::TransactionEnvelope
6
6
 
7
- @transaction_pool: untyped
7
+ @processor_pool: ProcessorPool
8
+
9
+ @transaction_pool: TransactionPool
8
10
 
9
11
  # @param processor_pool [ProcessorPool]
10
12
  # @param transaction_pool [TransactionPool]
11
- def initialize: (processor_pool: untyped, transaction_pool: untyped) -> void
13
+ def initialize: (processor_pool: ProcessorPool, transaction_pool: TransactionPool) -> void
12
14
 
13
15
  # Process a supported CDC work item.
14
16
  #
15
17
  # @param item [CDC::Core::ChangeEvent, CDC::Core::TransactionEnvelope]
16
18
  # @return [CDC::Core::ProcessorResult]
17
- def process: (untyped item) -> untyped
19
+ def process: (work_item item) -> CDC::Core::ProcessorResult
20
+ | (untyped item) -> CDC::Core::ProcessorResult
18
21
  end
19
22
  end
20
23
  end
@@ -2,36 +2,39 @@ module CDC
2
2
  module Parallel
3
3
  # High-level Ractor runtime facade for cdc-core processors.
4
4
  class Runtime
5
- @processor_pool: untyped
5
+ type work_item = CDC::Core::ChangeEvent | CDC::Core::TransactionEnvelope
6
6
 
7
- @transaction_pool: untyped
7
+ @processor_pool: ProcessorPool
8
8
 
9
- @router: untyped
9
+ @transaction_pool: TransactionPool
10
10
 
11
- @shutdown: untyped
11
+ @router: Router
12
+
13
+ @shutdown: bool
12
14
 
13
15
  # @param processor [CDC::Core::Processor]
14
16
  # @param size [Integer]
15
17
  # @param timeout [Float, nil]
16
18
  # @return [void]
17
- def initialize: (processor: untyped, ?size: untyped, ?timeout: untyped?) -> void
19
+ def initialize: (processor: CDC::Core::Processor, ?size: Integer, ?timeout: Numeric?) -> void
18
20
 
19
21
  # Process a ChangeEvent or TransactionEnvelope.
20
22
  #
21
23
  # @param item [CDC::Core::ChangeEvent, CDC::Core::TransactionEnvelope]
22
24
  # @return [CDC::Core::ProcessorResult]
23
- def process: (untyped item) -> untyped
25
+ def process: (work_item item) -> CDC::Core::ProcessorResult
26
+ | (untyped item) -> CDC::Core::ProcessorResult
24
27
 
25
28
  # Alias for transaction-oriented processing.
26
29
  #
27
30
  # @param transaction [CDC::Core::TransactionEnvelope]
28
31
  # @return [CDC::Core::ProcessorResult]
29
- def process_transaction: (untyped transaction) -> untyped
32
+ def process_transaction: (CDC::Core::TransactionEnvelope transaction) -> CDC::Core::ProcessorResult
30
33
 
31
34
  # Shut down all runtime resources.
32
35
  #
33
36
  # @return [void]
34
- def shutdown: () -> (nil | untyped)
37
+ def shutdown: () -> nil
35
38
  end
36
39
  end
37
40
  end
@@ -2,23 +2,23 @@ module CDC
2
2
  module Parallel
3
3
  # Processes a TransactionEnvelope as a single ordering-preserving unit.
4
4
  class TransactionPool
5
- @processor_pool: untyped
5
+ @processor_pool: ProcessorPool
6
6
 
7
7
  # @param processor [CDC::Core::Processor]
8
8
  # @param size [Integer]
9
9
  # @param timeout [Float, nil]
10
- def initialize: (processor: untyped, ?size: untyped, ?timeout: untyped?) -> void
10
+ def initialize: (processor: CDC::Core::Processor, ?size: Integer, ?timeout: Numeric?) -> void
11
11
 
12
12
  # Process all events inside a transaction envelope.
13
13
  #
14
14
  # @param transaction [CDC::Core::TransactionEnvelope]
15
15
  # @return [CDC::Core::ProcessorResult]
16
- def process: (untyped transaction) -> untyped
16
+ def process: (CDC::Core::TransactionEnvelope transaction) -> CDC::Core::ProcessorResult
17
17
 
18
18
  # Shut down worker resources.
19
19
  #
20
20
  # @return [void]
21
- def shutdown: () -> untyped
21
+ def shutdown: () -> nil
22
22
  end
23
23
  end
24
24
  end
@@ -1,6 +1,6 @@
1
1
  module CDC
2
2
  module Parallel
3
3
  # Current cdc-parallel version.
4
- VERSION: "0.2.0"
4
+ VERSION: "0.2.3"
5
5
  end
6
6
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cdc-parallel
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 0.2.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ken C. Demanawa
@@ -13,30 +13,16 @@ dependencies:
13
13
  name: cdc-core
14
14
  requirement: !ruby/object:Gem::Requirement
15
15
  requirements:
16
- - - "~>"
16
+ - - ">="
17
17
  - !ruby/object:Gem::Version
18
18
  version: '0.1'
19
19
  type: :runtime
20
20
  prerelease: false
21
21
  version_requirements: !ruby/object:Gem::Requirement
22
22
  requirements:
23
- - - "~>"
23
+ - - ">="
24
24
  - !ruby/object:Gem::Version
25
25
  version: '0.1'
26
- - !ruby/object:Gem::Dependency
27
- name: ractor-pool
28
- requirement: !ruby/object:Gem::Requirement
29
- requirements:
30
- - - "~>"
31
- - !ruby/object:Gem::Version
32
- version: 0.4.0
33
- type: :runtime
34
- prerelease: false
35
- version_requirements: !ruby/object:Gem::Requirement
36
- requirements:
37
- - - "~>"
38
- - !ruby/object:Gem::Version
39
- version: 0.4.0
40
26
  description: |
41
27
  cdc-parallel provides optional Ractor-backed parallel execution for
42
28
  cdc-core. It accelerates PostgreSQL Change Data Capture (CDC) event
@@ -70,15 +56,11 @@ files:
70
56
  - sig/cdc/parallel/transaction_pool.rbs
71
57
  - sig/cdc/parallel/version.rbs
72
58
  - sig/cdc_parallel.rbs
73
- - sig/shims/cdc_core.rbs
74
- - sig/shims/data_define.rbs
75
- - sig/shims/etc.rbs
76
- - sig/shims/timeout.rbs
77
- homepage: https://kanutocd.github.io/cdc-parallel/
59
+ homepage: https://github.com/kanutocd/cdc-parallel
78
60
  licenses:
79
61
  - MIT
80
62
  metadata:
81
- homepage_uri: https://kanutocd.github.io/cdc-parallel/
63
+ homepage_uri: https://github.com/kanutocd/cdc-parallel
82
64
  source_code_uri: https://github.com/kanutocd/cdc-parallel
83
65
  changelog_uri: https://github.com/kanutocd/cdc-parallel/blob/main/CHANGELOG.md
84
66
  documentation_uri: https://kanutocd.github.io/cdc-parallel/
@@ -1,14 +0,0 @@
1
- module CDC
2
- module Core
3
- class ProcessorResult
4
- def self.success: (untyped event) -> ProcessorResult
5
- def self.failure: (untyped error, ?event: untyped) -> ProcessorResult
6
- end
7
-
8
- class ChangeEvent
9
- end
10
-
11
- class TransactionEnvelope
12
- end
13
- end
14
- end
File without changes
data/sig/shims/etc.rbs DELETED
@@ -1,3 +0,0 @@
1
- module Etc
2
- def self.nprocessors: () -> Integer
3
- end
@@ -1,3 +0,0 @@
1
- module Timeout
2
- def self.timeout: (untyped sec, untyped klass) { () -> untyped } -> untyped
3
- end