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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +48 -21
- data/README.md +54 -48
- data/lib/cdc/parallel/configuration.rb +28 -5
- data/lib/cdc/parallel/errors.rb +59 -5
- data/lib/cdc/parallel/processor_pool.rb +198 -44
- data/lib/cdc/parallel/result_collector.rb +43 -2
- data/lib/cdc/parallel/router.rb +26 -1
- data/lib/cdc/parallel/runtime.rb +65 -4
- data/lib/cdc/parallel/transaction_pool.rb +54 -3
- data/lib/cdc/parallel/version.rb +6 -1
- data/lib/cdc/parallel.rb +33 -1
- data/sig/cdc/parallel/configuration.rbs +8 -2
- data/sig/cdc/parallel/errors.rbs +7 -7
- data/sig/cdc/parallel/processor_pool.rbs +33 -16
- data/sig/cdc/parallel/result_collector.rbs +6 -4
- data/sig/cdc/parallel/router.rbs +7 -4
- data/sig/cdc/parallel/runtime.rbs +11 -8
- data/sig/cdc/parallel/transaction_pool.rbs +4 -4
- data/sig/cdc/parallel/version.rbs +1 -1
- metadata +5 -23
- data/sig/shims/cdc_core.rbs +0 -14
- data/sig/shims/data_define.rbs +0 -0
- data/sig/shims/etc.rbs +0 -3
- data/sig/shims/timeout.rbs +0 -3
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
|
-
|
|
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
|
data/sig/cdc/parallel/errors.rbs
CHANGED
|
@@ -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:
|
|
21
|
+
@original_class: String
|
|
22
22
|
|
|
23
|
-
@original_message:
|
|
23
|
+
@original_message: String
|
|
24
24
|
|
|
25
|
-
@original_backtrace:
|
|
25
|
+
@original_backtrace: Array[String]
|
|
26
26
|
|
|
27
|
-
attr_reader original_class:
|
|
27
|
+
attr_reader original_class: String
|
|
28
28
|
|
|
29
|
-
attr_reader original_message:
|
|
29
|
+
attr_reader original_message: String
|
|
30
30
|
|
|
31
|
-
attr_reader original_backtrace:
|
|
31
|
+
attr_reader original_backtrace: Array[String]
|
|
32
32
|
|
|
33
|
-
def initialize: (original_class:
|
|
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
|
-
|
|
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:
|
|
12
|
+
@configuration: Configuration
|
|
8
13
|
|
|
9
|
-
@workers:
|
|
14
|
+
@workers: Array[Ractor]
|
|
15
|
+
|
|
16
|
+
@worker_inboxes: Array[worker_inbox]
|
|
10
17
|
|
|
11
18
|
@next_worker: Integer
|
|
12
19
|
|
|
13
|
-
@
|
|
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:
|
|
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: (
|
|
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: (
|
|
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: () ->
|
|
45
|
+
def shutdown: () -> nil?
|
|
37
46
|
|
|
38
47
|
private
|
|
39
48
|
|
|
40
|
-
def
|
|
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!: (
|
|
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
|
|
65
|
+
def start_worker: (CDC::Core::Processor processor, Ractor::Port boot_port) -> Ractor
|
|
49
66
|
|
|
50
|
-
def
|
|
67
|
+
def next_worker_inbox: () -> worker_inbox
|
|
51
68
|
|
|
52
|
-
def collect_results: (
|
|
69
|
+
def collect_results: (reply_port reply_port, Integer count) -> Array[result]
|
|
53
70
|
|
|
54
|
-
def collect_results_without_timeout: (
|
|
71
|
+
def collect_results_without_timeout: (reply_port reply_port, Array[result?] results) -> untyped
|
|
55
72
|
|
|
56
|
-
def collect_results_with_timeout: (
|
|
73
|
+
def collect_results_with_timeout: (reply_port reply_port, Array[result?] results) -> untyped
|
|
57
74
|
|
|
58
|
-
def timeout_results: (
|
|
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: (
|
|
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: (
|
|
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) ->
|
|
25
|
+
def self.normalize: (CDC::Core::ProcessorResult | failure_payload | untyped value) -> CDC::Core::ProcessorResult
|
|
24
26
|
|
|
25
|
-
def self.worker_failure?: (untyped value) ->
|
|
27
|
+
def self.worker_failure?: (untyped value) -> bool
|
|
26
28
|
end
|
|
27
29
|
end
|
|
28
30
|
end
|
data/sig/cdc/parallel/router.rbs
CHANGED
|
@@ -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
|
-
|
|
5
|
+
type work_item = CDC::Core::ChangeEvent | CDC::Core::TransactionEnvelope
|
|
6
6
|
|
|
7
|
-
@
|
|
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:
|
|
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: (
|
|
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
|
-
|
|
5
|
+
type work_item = CDC::Core::ChangeEvent | CDC::Core::TransactionEnvelope
|
|
6
6
|
|
|
7
|
-
@
|
|
7
|
+
@processor_pool: ProcessorPool
|
|
8
8
|
|
|
9
|
-
@
|
|
9
|
+
@transaction_pool: TransactionPool
|
|
10
10
|
|
|
11
|
-
@
|
|
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:
|
|
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: (
|
|
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: (
|
|
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: () ->
|
|
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:
|
|
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:
|
|
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: (
|
|
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: () ->
|
|
21
|
+
def shutdown: () -> nil
|
|
22
22
|
end
|
|
23
23
|
end
|
|
24
24
|
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.
|
|
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
|
-
|
|
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://
|
|
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/
|
data/sig/shims/cdc_core.rbs
DELETED
|
@@ -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
|
data/sig/shims/data_define.rbs
DELETED
|
File without changes
|
data/sig/shims/etc.rbs
DELETED
data/sig/shims/timeout.rbs
DELETED