cdc-parallel 0.2.2 → 0.2.4
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 +59 -21
- data/README.md +54 -48
- data/lib/cdc/parallel/configuration.rb +33 -6
- data/lib/cdc/parallel/errors.rb +59 -5
- data/lib/cdc/parallel/processor_pool.rb +522 -57
- data/lib/cdc/parallel/result_collector.rb +49 -2
- data/lib/cdc/parallel/router.rb +26 -1
- data/lib/cdc/parallel/runtime.rb +135 -7
- data/lib/cdc/parallel/transaction_pool.rb +87 -5
- data/lib/cdc/parallel/version.rb +6 -1
- data/lib/cdc/parallel.rb +39 -1
- data/sig/cdc/parallel/configuration.rbs +14 -2
- data/sig/cdc/parallel/errors.rbs +7 -7
- data/sig/cdc/parallel/processor_pool.rbs +112 -24
- data/sig/cdc/parallel/result_collector.rbs +6 -4
- data/sig/cdc/parallel/router.rbs +7 -4
- data/sig/cdc/parallel/runtime.rbs +43 -12
- data/sig/cdc/parallel/transaction_pool.rbs +15 -5
- 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
|
@@ -2,60 +2,148 @@ module CDC
|
|
|
2
2
|
module Parallel
|
|
3
3
|
# Executes one Ractor-safe processor in pre-warmed persistent Ractor workers.
|
|
4
4
|
class ProcessorPool
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
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
|
+
|
|
11
|
+
@processor: CDC::Core::Processor
|
|
12
|
+
@configuration: Configuration
|
|
13
|
+
@slots: Array[WorkerSlot]
|
|
14
|
+
@workers: Array[Ractor]
|
|
15
|
+
@worker_inboxes: Array[worker_inbox]
|
|
11
16
|
@next_worker: Integer
|
|
12
|
-
|
|
13
|
-
@shutdown:
|
|
17
|
+
@dispatch_mutex: Mutex
|
|
18
|
+
@shutdown: bool
|
|
19
|
+
@manage_lifecycle: bool
|
|
14
20
|
|
|
15
21
|
# @param processor [CDC::Core::Processor]
|
|
16
22
|
# @param size [Integer]
|
|
17
|
-
# @param timeout [
|
|
23
|
+
# @param timeout [Numeric, nil]
|
|
24
|
+
# @param supervision [Boolean]
|
|
25
|
+
# @param max_respawns [Integer]
|
|
26
|
+
# @param respawn_window [Numeric]
|
|
27
|
+
# @param respawn_cooldown [Numeric]
|
|
28
|
+
# @param manage_lifecycle [Boolean]
|
|
18
29
|
# @return [void]
|
|
19
|
-
def initialize: (
|
|
30
|
+
def initialize: (
|
|
31
|
+
processor: CDC::Core::Processor,
|
|
32
|
+
?size: Integer,
|
|
33
|
+
?timeout: Numeric?,
|
|
34
|
+
?supervision: bool,
|
|
35
|
+
?max_respawns: Integer,
|
|
36
|
+
?respawn_window: Numeric,
|
|
37
|
+
?respawn_cooldown: Numeric,
|
|
38
|
+
?manage_lifecycle: bool
|
|
39
|
+
) -> void
|
|
40
|
+
|
|
41
|
+
# Total worker-slot respawns since pool boot.
|
|
42
|
+
#
|
|
43
|
+
# @return [Integer]
|
|
44
|
+
def respawns: () -> Integer
|
|
45
|
+
|
|
46
|
+
# Whether any worker slot is in crash-loop cooldown.
|
|
47
|
+
#
|
|
48
|
+
# @return [Boolean]
|
|
49
|
+
def degraded?: () -> bool
|
|
20
50
|
|
|
21
51
|
# Process one work item synchronously.
|
|
22
52
|
#
|
|
23
53
|
# @param item [Object]
|
|
24
54
|
# @return [CDC::Core::ProcessorResult]
|
|
25
|
-
def process: (
|
|
55
|
+
def process: (work_item item) -> result
|
|
26
56
|
|
|
27
57
|
# Process many work items using the pre-warmed worker pool.
|
|
28
58
|
#
|
|
29
59
|
# @param items [Array<Object>]
|
|
30
60
|
# @return [Array<CDC::Core::ProcessorResult>]
|
|
31
|
-
def process_many: (
|
|
61
|
+
def process_many: (Array[work_item] items) -> Array[result]
|
|
32
62
|
|
|
33
|
-
# Shut down the pool.
|
|
63
|
+
# Shut down the pool and call processor lifecycle hooks if manage_lifecycle is true.
|
|
34
64
|
#
|
|
35
65
|
# @return [void]
|
|
36
|
-
def shutdown: () ->
|
|
66
|
+
def shutdown: () -> void
|
|
37
67
|
|
|
38
68
|
private
|
|
39
69
|
|
|
40
|
-
def
|
|
70
|
+
def self.start_worker: (CDC::Core::Processor processor, Ractor::Port boot_port) -> Ractor
|
|
71
|
+
|
|
72
|
+
def self.run_worker_loop: (untyped safe_processor, untyped inbox) -> nil
|
|
73
|
+
|
|
74
|
+
def self.worker_response: (untyped safe_processor, work_item item) -> worker_response
|
|
75
|
+
|
|
76
|
+
def dispatch: (Array[work_item] work_items, reply_port reply_port) -> Array[WorkerSlot?]
|
|
77
|
+
|
|
78
|
+
def signal_workers: () -> void
|
|
79
|
+
|
|
80
|
+
def wait_for_workers: () -> void
|
|
81
|
+
|
|
82
|
+
def wait_for_workers_with_timeout: () -> void
|
|
83
|
+
|
|
84
|
+
def validate_processor!: (CDC::Core::Processor processor) -> void
|
|
85
|
+
|
|
86
|
+
def next_worker_slot: () -> WorkerSlot
|
|
87
|
+
|
|
88
|
+
def collect_results: (reply_port reply_port, Integer count, ?Array[WorkerSlot?] assignments) -> Array[result?]
|
|
41
89
|
|
|
42
|
-
def
|
|
90
|
+
def collect_results_without_timeout: (reply_port reply_port, Array[result?] results, Array[WorkerSlot?] assignments) -> Array[result?]
|
|
43
91
|
|
|
44
|
-
def
|
|
92
|
+
def collect_results_with_timeout: (reply_port reply_port, Array[result?] results, Array[WorkerSlot?] assignments) -> Array[result?]
|
|
45
93
|
|
|
46
|
-
def
|
|
94
|
+
def timeout_results: (Array[result?] results) -> Array[result]
|
|
47
95
|
|
|
48
|
-
|
|
96
|
+
# One supervised worker position in the pool.
|
|
97
|
+
class WorkerSlot
|
|
98
|
+
@index: Integer
|
|
99
|
+
@processor: CDC::Core::Processor
|
|
100
|
+
@supervision: bool
|
|
101
|
+
@max_respawns: Integer
|
|
102
|
+
@respawn_window: Float
|
|
103
|
+
@respawn_cooldown: Float
|
|
104
|
+
@lock: Mutex
|
|
105
|
+
@worker: Ractor
|
|
106
|
+
@inbox: Ractor::Port
|
|
107
|
+
@inflight: Hash[Integer, Ractor::Port]
|
|
108
|
+
@crashes: Array[Float]
|
|
109
|
+
@respawns: Integer
|
|
110
|
+
@shutdown: bool
|
|
111
|
+
@degraded_until: Float?
|
|
112
|
+
@supervisor_thread: Thread
|
|
49
113
|
|
|
50
|
-
|
|
114
|
+
attr_reader respawns: Integer
|
|
51
115
|
|
|
52
|
-
|
|
116
|
+
def initialize: (
|
|
117
|
+
index: Integer,
|
|
118
|
+
processor: CDC::Core::Processor,
|
|
119
|
+
supervision: bool,
|
|
120
|
+
max_respawns: Integer,
|
|
121
|
+
respawn_window: Numeric,
|
|
122
|
+
respawn_cooldown: Numeric
|
|
123
|
+
) -> void
|
|
53
124
|
|
|
54
|
-
|
|
125
|
+
def worker: () -> Ractor
|
|
126
|
+
def inbox: () -> Ractor::Port
|
|
127
|
+
def send_work: (Integer index, untyped item, Ractor::Port reply_port) -> void
|
|
128
|
+
def complete: (Integer index) -> void
|
|
129
|
+
def degraded?: () -> bool
|
|
130
|
+
def shutdown: () -> void
|
|
131
|
+
def join: () -> void
|
|
55
132
|
|
|
56
|
-
|
|
133
|
+
private
|
|
57
134
|
|
|
58
|
-
|
|
135
|
+
def boot!: () -> void
|
|
136
|
+
def supervise: () -> void
|
|
137
|
+
def wait_for_worker_death: (Ractor current_worker) -> Exception
|
|
138
|
+
def fail_inflight: (Exception cause) -> void
|
|
139
|
+
def send_failure: (Ractor::Port reply_port, Integer index, Exception error) -> void
|
|
140
|
+
def require_failure: (Exception? failure) -> Exception
|
|
141
|
+
def send_to_inbox: (untyped inbox, untyped message) -> void
|
|
142
|
+
def cool_down_if_needed: () -> void
|
|
143
|
+
def crash_loop?: () -> bool
|
|
144
|
+
def shutting_down?: () -> bool
|
|
145
|
+
def degraded_locked?: () -> bool
|
|
146
|
+
end
|
|
59
147
|
end
|
|
60
148
|
end
|
|
61
149
|
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,67 @@ 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
|
-
@
|
|
8
|
-
|
|
9
|
-
@
|
|
10
|
-
|
|
11
|
-
@shutdown:
|
|
7
|
+
@processor: CDC::Core::Processor
|
|
8
|
+
@processor_pool: ProcessorPool
|
|
9
|
+
@transaction_pool: TransactionPool
|
|
10
|
+
@router: Router
|
|
11
|
+
@shutdown: bool
|
|
12
12
|
|
|
13
13
|
# @param processor [CDC::Core::Processor]
|
|
14
14
|
# @param size [Integer]
|
|
15
|
-
# @param timeout [
|
|
15
|
+
# @param timeout [Numeric, nil]
|
|
16
16
|
# @return [void]
|
|
17
|
-
def initialize: (
|
|
17
|
+
def initialize: (
|
|
18
|
+
processor: CDC::Core::Processor,
|
|
19
|
+
?size: Integer,
|
|
20
|
+
?timeout: Numeric?,
|
|
21
|
+
?supervision: bool,
|
|
22
|
+
?max_respawns: Integer,
|
|
23
|
+
?respawn_window: Numeric,
|
|
24
|
+
?respawn_cooldown: Numeric
|
|
25
|
+
) -> void
|
|
18
26
|
|
|
19
27
|
# Process a ChangeEvent or TransactionEnvelope.
|
|
20
28
|
#
|
|
21
29
|
# @param item [CDC::Core::ChangeEvent, CDC::Core::TransactionEnvelope]
|
|
22
30
|
# @return [CDC::Core::ProcessorResult]
|
|
23
|
-
def process: (
|
|
31
|
+
def process: (work_item item) -> CDC::Core::ProcessorResult
|
|
32
|
+
| (untyped item) -> CDC::Core::ProcessorResult
|
|
24
33
|
|
|
25
34
|
# Alias for transaction-oriented processing.
|
|
26
35
|
#
|
|
27
36
|
# @param transaction [CDC::Core::TransactionEnvelope]
|
|
28
37
|
# @return [CDC::Core::ProcessorResult]
|
|
29
|
-
def process_transaction: (
|
|
38
|
+
def process_transaction: (CDC::Core::TransactionEnvelope transaction) -> CDC::Core::ProcessorResult
|
|
30
39
|
|
|
31
|
-
# Shut down all runtime resources.
|
|
40
|
+
# Shut down all runtime resources and call processor lifecycle hooks.
|
|
32
41
|
#
|
|
33
42
|
# @return [void]
|
|
34
|
-
def shutdown: () ->
|
|
43
|
+
def shutdown: () -> void
|
|
44
|
+
|
|
45
|
+
private
|
|
46
|
+
|
|
47
|
+
# Build keyword arguments shared by internal pools.
|
|
48
|
+
def build_pool_options: (
|
|
49
|
+
processor: CDC::Core::Processor,
|
|
50
|
+
size: Integer,
|
|
51
|
+
timeout: Numeric?,
|
|
52
|
+
supervision: bool,
|
|
53
|
+
max_respawns: Integer,
|
|
54
|
+
respawn_window: Numeric,
|
|
55
|
+
respawn_cooldown: Numeric
|
|
56
|
+
) -> {
|
|
57
|
+
processor: CDC::Core::Processor,
|
|
58
|
+
size: Integer,
|
|
59
|
+
timeout: Numeric?,
|
|
60
|
+
supervision: bool,
|
|
61
|
+
max_respawns: Integer,
|
|
62
|
+
respawn_window: Numeric,
|
|
63
|
+
respawn_cooldown: Numeric,
|
|
64
|
+
manage_lifecycle: false
|
|
65
|
+
}
|
|
35
66
|
end
|
|
36
67
|
end
|
|
37
68
|
end
|
|
@@ -2,23 +2,33 @@ 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
|
-
# @param timeout [
|
|
10
|
-
|
|
9
|
+
# @param timeout [Numeric, nil]
|
|
10
|
+
# @param manage_lifecycle [Boolean]
|
|
11
|
+
def initialize: (
|
|
12
|
+
processor: CDC::Core::Processor,
|
|
13
|
+
?size: Integer,
|
|
14
|
+
?timeout: Numeric?,
|
|
15
|
+
?supervision: bool,
|
|
16
|
+
?max_respawns: Integer,
|
|
17
|
+
?respawn_window: Numeric,
|
|
18
|
+
?respawn_cooldown: Numeric,
|
|
19
|
+
?manage_lifecycle: bool
|
|
20
|
+
) -> void
|
|
11
21
|
|
|
12
22
|
# Process all events inside a transaction envelope.
|
|
13
23
|
#
|
|
14
24
|
# @param transaction [CDC::Core::TransactionEnvelope]
|
|
15
25
|
# @return [CDC::Core::ProcessorResult]
|
|
16
|
-
def process: (
|
|
26
|
+
def process: (CDC::Core::TransactionEnvelope transaction) -> CDC::Core::ProcessorResult
|
|
17
27
|
|
|
18
28
|
# Shut down worker resources.
|
|
19
29
|
#
|
|
20
30
|
# @return [void]
|
|
21
|
-
def shutdown: () ->
|
|
31
|
+
def shutdown: () -> void
|
|
22
32
|
end
|
|
23
33
|
end
|
|
24
34
|
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.4
|
|
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