itsi-scheduler 0.1.0 → 0.1.2
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/Cargo.lock +219 -23
- data/Rakefile +7 -1
- data/ext/itsi_error/Cargo.toml +2 -0
- data/ext/itsi_error/src/from.rs +70 -0
- data/ext/itsi_error/src/lib.rs +10 -37
- data/ext/itsi_instrument_entry/Cargo.toml +15 -0
- data/ext/itsi_instrument_entry/src/lib.rs +31 -0
- data/ext/itsi_rb_helpers/Cargo.toml +2 -0
- data/ext/itsi_rb_helpers/src/heap_value.rs +121 -0
- data/ext/itsi_rb_helpers/src/lib.rs +90 -10
- data/ext/itsi_scheduler/Cargo.toml +9 -1
- data/ext/itsi_scheduler/extconf.rb +1 -1
- data/ext/itsi_scheduler/src/itsi_scheduler/io_helpers.rs +56 -0
- data/ext/itsi_scheduler/src/itsi_scheduler/io_waiter.rs +44 -0
- data/ext/itsi_scheduler/src/itsi_scheduler/timer.rs +44 -0
- data/ext/itsi_scheduler/src/itsi_scheduler.rs +308 -0
- data/ext/itsi_scheduler/src/lib.rs +31 -10
- data/ext/itsi_server/Cargo.toml +41 -0
- data/ext/itsi_server/extconf.rb +6 -0
- data/ext/itsi_server/src/body_proxy/big_bytes.rs +104 -0
- data/ext/itsi_server/src/body_proxy/itsi_body_proxy.rs +122 -0
- data/ext/itsi_server/src/body_proxy/mod.rs +2 -0
- data/ext/itsi_server/src/lib.rs +103 -0
- data/ext/itsi_server/src/request/itsi_request.rs +277 -0
- data/ext/itsi_server/src/request/mod.rs +1 -0
- data/ext/itsi_server/src/response/itsi_response.rs +347 -0
- data/ext/itsi_server/src/response/mod.rs +1 -0
- data/ext/itsi_server/src/server/bind.rs +168 -0
- data/ext/itsi_server/src/server/bind_protocol.rs +37 -0
- data/ext/itsi_server/src/server/io_stream.rs +104 -0
- data/ext/itsi_server/src/server/itsi_ca/itsi_ca.crt +13 -0
- data/ext/itsi_server/src/server/itsi_ca/itsi_ca.key +5 -0
- data/ext/itsi_server/src/server/itsi_server.rs +230 -0
- data/ext/itsi_server/src/server/lifecycle_event.rs +8 -0
- data/ext/itsi_server/src/server/listener.rs +259 -0
- data/ext/itsi_server/src/server/mod.rs +11 -0
- data/ext/itsi_server/src/server/process_worker.rs +196 -0
- data/ext/itsi_server/src/server/serve_strategy/cluster_mode.rs +253 -0
- data/ext/itsi_server/src/server/serve_strategy/mod.rs +27 -0
- data/ext/itsi_server/src/server/serve_strategy/single_mode.rs +238 -0
- data/ext/itsi_server/src/server/signal.rs +57 -0
- data/ext/itsi_server/src/server/thread_worker.rs +368 -0
- data/ext/itsi_server/src/server/tls.rs +152 -0
- data/ext/itsi_tracing/Cargo.toml +4 -0
- data/ext/itsi_tracing/src/lib.rs +36 -6
- data/lib/itsi/scheduler/version.rb +1 -1
- data/lib/itsi/scheduler.rb +137 -1
- metadata +38 -4
data/lib/itsi/scheduler.rb
CHANGED
@@ -6,6 +6,142 @@ require_relative "scheduler/itsi_scheduler"
|
|
6
6
|
module Itsi
|
7
7
|
class Scheduler
|
8
8
|
class Error < StandardError; end
|
9
|
-
|
9
|
+
|
10
|
+
def self.resume_token
|
11
|
+
@resume_token ||= 0
|
12
|
+
@resume_token += 1
|
13
|
+
end
|
14
|
+
|
15
|
+
def initialize
|
16
|
+
@join_waiters = {}.compare_by_identity
|
17
|
+
@token_map = {}.compare_by_identity
|
18
|
+
@resume_tokens = {}.compare_by_identity
|
19
|
+
@unblocked = [[], []]
|
20
|
+
@unblock_idx = 0
|
21
|
+
@unblocked_mux = Mutex.new
|
22
|
+
@resume_fiber = method(:resume_fiber).to_proc
|
23
|
+
@resume_fiber_with_readiness = method(:resume_fiber_with_readiness).to_proc
|
24
|
+
@resume_blocked = method(:resume_blocked).to_proc
|
25
|
+
end
|
26
|
+
|
27
|
+
def block(_, timeout, fiber = Fiber.current, token = Scheduler.resume_token)
|
28
|
+
@join_waiters[fiber] = true
|
29
|
+
|
30
|
+
start_timer(timeout, token) if timeout
|
31
|
+
@resume_tokens[token] = fiber
|
32
|
+
@token_map[fiber] = token
|
33
|
+
Fiber.yield
|
34
|
+
ensure
|
35
|
+
@resume_tokens.delete(token)
|
36
|
+
@token_map.delete(fiber)
|
37
|
+
@join_waiters.delete(fiber)
|
38
|
+
end
|
39
|
+
|
40
|
+
# Register an IO waiter.
|
41
|
+
# This will get resumed by our scheduler inside the call to
|
42
|
+
# fetch_events.
|
43
|
+
def io_wait(io, events, duration)
|
44
|
+
fiber = Fiber.current
|
45
|
+
token = Scheduler.resume_token
|
46
|
+
readiness = register_io_wait(io.fileno, events, duration, token)
|
47
|
+
readiness || block(nil, duration, fiber, token)
|
48
|
+
end
|
49
|
+
|
50
|
+
def unblock(_blocker, fiber)
|
51
|
+
@unblocked_mux.synchronize do
|
52
|
+
@unblocked[@unblock_idx] << fiber
|
53
|
+
end
|
54
|
+
wake
|
55
|
+
end
|
56
|
+
|
57
|
+
def kernel_sleep(duration)
|
58
|
+
block nil, duration
|
59
|
+
end
|
60
|
+
|
61
|
+
def tick
|
62
|
+
events = fetch_due_events
|
63
|
+
timers = fetch_due_timers
|
64
|
+
unblocked = switch_unblock_batch
|
65
|
+
events&.each(&@resume_fiber_with_readiness)
|
66
|
+
unblocked.each(&@resume_blocked)
|
67
|
+
unblocked.clear
|
68
|
+
timers&.each(&@resume_fiber)
|
69
|
+
end
|
70
|
+
|
71
|
+
def resume_fiber(token)
|
72
|
+
if (fiber = @resume_tokens.delete(token))
|
73
|
+
fiber.resume
|
74
|
+
end
|
75
|
+
rescue StandardError => e
|
76
|
+
warn "Failed to resume fiber #{fiber}: #{e.message}"
|
77
|
+
end
|
78
|
+
|
79
|
+
def resume_fiber_with_readiness((token, readiness))
|
80
|
+
if (fiber = @resume_tokens.delete(token))
|
81
|
+
fiber.resume(readiness)
|
82
|
+
end
|
83
|
+
rescue StandardError => e
|
84
|
+
warn "Failed to resume fiber #{fiber}: #{e.message}"
|
85
|
+
end
|
86
|
+
|
87
|
+
def resume_blocked(fiber)
|
88
|
+
if (token = @token_map[fiber])
|
89
|
+
resume_fiber(token)
|
90
|
+
elsif fiber.alive?
|
91
|
+
fiber.resume
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def switch_unblock_batch
|
96
|
+
@unblocked_mux.synchronize do
|
97
|
+
current = @unblocked[@unblock_idx]
|
98
|
+
@unblock_idx = (@unblock_idx + 1) % 2
|
99
|
+
current
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
# Yields upwards to the scheduler, with an intention to
|
104
|
+
# resume the fiber that yielded ASAP.
|
105
|
+
def yield
|
106
|
+
kernel_sleep(0) if work?
|
107
|
+
end
|
108
|
+
|
109
|
+
# Keep running until we've got no timers we're awaiting, no pending IO, no temporary yields,
|
110
|
+
# no pending unblocks.
|
111
|
+
def work?
|
112
|
+
!@unblocked[@unblock_idx].empty? || !@join_waiters.empty? || has_pending_io?
|
113
|
+
end
|
114
|
+
|
115
|
+
# Run until no more work needs doing.
|
116
|
+
def run
|
117
|
+
tick while work?
|
118
|
+
debug "Exit Scheduler"
|
119
|
+
end
|
120
|
+
|
121
|
+
# Hook invoked at the end of the thread.
|
122
|
+
# Will start our scheduler's Reactor.
|
123
|
+
def scheduler_close
|
124
|
+
run
|
125
|
+
ensure
|
126
|
+
@closed ||= true
|
127
|
+
freeze
|
128
|
+
end
|
129
|
+
|
130
|
+
# Need to defer to Process::Status rather than our extension
|
131
|
+
# as we don't have a means of creating our own Process::Status.
|
132
|
+
def process_wait(pid, flags)
|
133
|
+
Thread.new do
|
134
|
+
Process::Status.wait(pid, flags)
|
135
|
+
end.value
|
136
|
+
end
|
137
|
+
|
138
|
+
def closed?
|
139
|
+
@closed
|
140
|
+
end
|
141
|
+
|
142
|
+
# Spin up a new fiber and immediately resume it.
|
143
|
+
def fiber(&blk)
|
144
|
+
Fiber.new(blocking: false, &blk).tap(&:resume)
|
145
|
+
end
|
10
146
|
end
|
11
147
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: itsi-scheduler
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Wouter Coppieters
|
8
8
|
bindir: exe
|
9
9
|
cert_chain: []
|
10
|
-
date: 2025-03-
|
10
|
+
date: 2025-03-13 00:00:00.000000000 Z
|
11
11
|
dependencies:
|
12
12
|
- !ruby/object:Gem::Dependency
|
13
13
|
name: libclang
|
@@ -56,13 +56,47 @@ files:
|
|
56
56
|
- Rakefile
|
57
57
|
- ext/itsi_error/Cargo.lock
|
58
58
|
- ext/itsi_error/Cargo.toml
|
59
|
+
- ext/itsi_error/src/from.rs
|
59
60
|
- ext/itsi_error/src/lib.rs
|
61
|
+
- ext/itsi_instrument_entry/Cargo.toml
|
62
|
+
- ext/itsi_instrument_entry/src/lib.rs
|
60
63
|
- ext/itsi_rb_helpers/Cargo.lock
|
61
64
|
- ext/itsi_rb_helpers/Cargo.toml
|
65
|
+
- ext/itsi_rb_helpers/src/heap_value.rs
|
62
66
|
- ext/itsi_rb_helpers/src/lib.rs
|
63
67
|
- ext/itsi_scheduler/Cargo.toml
|
64
68
|
- ext/itsi_scheduler/extconf.rb
|
69
|
+
- ext/itsi_scheduler/src/itsi_scheduler.rs
|
70
|
+
- ext/itsi_scheduler/src/itsi_scheduler/io_helpers.rs
|
71
|
+
- ext/itsi_scheduler/src/itsi_scheduler/io_waiter.rs
|
72
|
+
- ext/itsi_scheduler/src/itsi_scheduler/timer.rs
|
65
73
|
- ext/itsi_scheduler/src/lib.rs
|
74
|
+
- ext/itsi_server/Cargo.toml
|
75
|
+
- ext/itsi_server/extconf.rb
|
76
|
+
- ext/itsi_server/src/body_proxy/big_bytes.rs
|
77
|
+
- ext/itsi_server/src/body_proxy/itsi_body_proxy.rs
|
78
|
+
- ext/itsi_server/src/body_proxy/mod.rs
|
79
|
+
- ext/itsi_server/src/lib.rs
|
80
|
+
- ext/itsi_server/src/request/itsi_request.rs
|
81
|
+
- ext/itsi_server/src/request/mod.rs
|
82
|
+
- ext/itsi_server/src/response/itsi_response.rs
|
83
|
+
- ext/itsi_server/src/response/mod.rs
|
84
|
+
- ext/itsi_server/src/server/bind.rs
|
85
|
+
- ext/itsi_server/src/server/bind_protocol.rs
|
86
|
+
- ext/itsi_server/src/server/io_stream.rs
|
87
|
+
- ext/itsi_server/src/server/itsi_ca/itsi_ca.crt
|
88
|
+
- ext/itsi_server/src/server/itsi_ca/itsi_ca.key
|
89
|
+
- ext/itsi_server/src/server/itsi_server.rs
|
90
|
+
- ext/itsi_server/src/server/lifecycle_event.rs
|
91
|
+
- ext/itsi_server/src/server/listener.rs
|
92
|
+
- ext/itsi_server/src/server/mod.rs
|
93
|
+
- ext/itsi_server/src/server/process_worker.rs
|
94
|
+
- ext/itsi_server/src/server/serve_strategy/cluster_mode.rs
|
95
|
+
- ext/itsi_server/src/server/serve_strategy/mod.rs
|
96
|
+
- ext/itsi_server/src/server/serve_strategy/single_mode.rs
|
97
|
+
- ext/itsi_server/src/server/signal.rs
|
98
|
+
- ext/itsi_server/src/server/thread_worker.rs
|
99
|
+
- ext/itsi_server/src/server/tls.rs
|
66
100
|
- ext/itsi_tracing/Cargo.lock
|
67
101
|
- ext/itsi_tracing/Cargo.toml
|
68
102
|
- ext/itsi_tracing/src/lib.rs
|
@@ -83,12 +117,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
83
117
|
requirements:
|
84
118
|
- - ">="
|
85
119
|
- !ruby/object:Gem::Version
|
86
|
-
version: 3.
|
120
|
+
version: 3.0.0
|
87
121
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
88
122
|
requirements:
|
89
123
|
- - ">="
|
90
124
|
- !ruby/object:Gem::Version
|
91
|
-
version: 3.
|
125
|
+
version: 3.1.11
|
92
126
|
requirements: []
|
93
127
|
rubygems_version: 3.6.2
|
94
128
|
specification_version: 4
|