itsi-scheduler 0.2.22-aarch64-linux

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.
Files changed (149) hide show
  1. checksums.yaml +7 -0
  2. data/.rubocop.yml +8 -0
  3. data/Cargo.lock +997 -0
  4. data/Cargo.toml +7 -0
  5. data/Rakefile +39 -0
  6. data/ext/itsi_acme/Cargo.toml +86 -0
  7. data/ext/itsi_acme/examples/high_level.rs +63 -0
  8. data/ext/itsi_acme/examples/high_level_warp.rs +52 -0
  9. data/ext/itsi_acme/examples/low_level.rs +87 -0
  10. data/ext/itsi_acme/examples/low_level_axum.rs +66 -0
  11. data/ext/itsi_acme/src/acceptor.rs +81 -0
  12. data/ext/itsi_acme/src/acme.rs +354 -0
  13. data/ext/itsi_acme/src/axum.rs +86 -0
  14. data/ext/itsi_acme/src/cache.rs +39 -0
  15. data/ext/itsi_acme/src/caches/boxed.rs +80 -0
  16. data/ext/itsi_acme/src/caches/composite.rs +69 -0
  17. data/ext/itsi_acme/src/caches/dir.rs +106 -0
  18. data/ext/itsi_acme/src/caches/mod.rs +11 -0
  19. data/ext/itsi_acme/src/caches/no.rs +78 -0
  20. data/ext/itsi_acme/src/caches/test.rs +136 -0
  21. data/ext/itsi_acme/src/config.rs +172 -0
  22. data/ext/itsi_acme/src/https_helper.rs +69 -0
  23. data/ext/itsi_acme/src/incoming.rs +142 -0
  24. data/ext/itsi_acme/src/jose.rs +161 -0
  25. data/ext/itsi_acme/src/lib.rs +142 -0
  26. data/ext/itsi_acme/src/resolver.rs +59 -0
  27. data/ext/itsi_acme/src/state.rs +424 -0
  28. data/ext/itsi_error/Cargo.lock +368 -0
  29. data/ext/itsi_error/Cargo.toml +12 -0
  30. data/ext/itsi_error/src/lib.rs +140 -0
  31. data/ext/itsi_instrument_entry/Cargo.toml +15 -0
  32. data/ext/itsi_instrument_entry/src/lib.rs +31 -0
  33. data/ext/itsi_rb_helpers/Cargo.lock +355 -0
  34. data/ext/itsi_rb_helpers/Cargo.toml +11 -0
  35. data/ext/itsi_rb_helpers/src/heap_value.rs +139 -0
  36. data/ext/itsi_rb_helpers/src/lib.rs +232 -0
  37. data/ext/itsi_scheduler/Cargo.toml +24 -0
  38. data/ext/itsi_scheduler/extconf.rb +11 -0
  39. data/ext/itsi_scheduler/src/itsi_scheduler/io_helpers.rs +56 -0
  40. data/ext/itsi_scheduler/src/itsi_scheduler/io_waiter.rs +44 -0
  41. data/ext/itsi_scheduler/src/itsi_scheduler/timer.rs +44 -0
  42. data/ext/itsi_scheduler/src/itsi_scheduler.rs +320 -0
  43. data/ext/itsi_scheduler/src/lib.rs +39 -0
  44. data/ext/itsi_server/Cargo.lock +2956 -0
  45. data/ext/itsi_server/Cargo.toml +94 -0
  46. data/ext/itsi_server/src/default_responses/mod.rs +14 -0
  47. data/ext/itsi_server/src/env.rs +43 -0
  48. data/ext/itsi_server/src/lib.rs +154 -0
  49. data/ext/itsi_server/src/prelude.rs +2 -0
  50. data/ext/itsi_server/src/ruby_types/itsi_body_proxy/big_bytes.rs +116 -0
  51. data/ext/itsi_server/src/ruby_types/itsi_body_proxy/mod.rs +149 -0
  52. data/ext/itsi_server/src/ruby_types/itsi_grpc_call.rs +346 -0
  53. data/ext/itsi_server/src/ruby_types/itsi_grpc_response_stream/mod.rs +265 -0
  54. data/ext/itsi_server/src/ruby_types/itsi_http_request.rs +399 -0
  55. data/ext/itsi_server/src/ruby_types/itsi_http_response.rs +447 -0
  56. data/ext/itsi_server/src/ruby_types/itsi_server/file_watcher.rs +545 -0
  57. data/ext/itsi_server/src/ruby_types/itsi_server/itsi_server_config.rs +650 -0
  58. data/ext/itsi_server/src/ruby_types/itsi_server.rs +102 -0
  59. data/ext/itsi_server/src/ruby_types/mod.rs +48 -0
  60. data/ext/itsi_server/src/server/binds/bind.rs +204 -0
  61. data/ext/itsi_server/src/server/binds/bind_protocol.rs +37 -0
  62. data/ext/itsi_server/src/server/binds/listener.rs +485 -0
  63. data/ext/itsi_server/src/server/binds/mod.rs +4 -0
  64. data/ext/itsi_server/src/server/binds/tls/locked_dir_cache.rs +132 -0
  65. data/ext/itsi_server/src/server/binds/tls.rs +278 -0
  66. data/ext/itsi_server/src/server/byte_frame.rs +32 -0
  67. data/ext/itsi_server/src/server/frame_stream.rs +143 -0
  68. data/ext/itsi_server/src/server/http_message_types.rs +230 -0
  69. data/ext/itsi_server/src/server/io_stream.rs +128 -0
  70. data/ext/itsi_server/src/server/lifecycle_event.rs +12 -0
  71. data/ext/itsi_server/src/server/middleware_stack/middleware.rs +170 -0
  72. data/ext/itsi_server/src/server/middleware_stack/middlewares/allow_list.rs +63 -0
  73. data/ext/itsi_server/src/server/middleware_stack/middlewares/auth_api_key.rs +94 -0
  74. data/ext/itsi_server/src/server/middleware_stack/middlewares/auth_basic.rs +93 -0
  75. data/ext/itsi_server/src/server/middleware_stack/middlewares/auth_jwt.rs +343 -0
  76. data/ext/itsi_server/src/server/middleware_stack/middlewares/cache_control.rs +151 -0
  77. data/ext/itsi_server/src/server/middleware_stack/middlewares/compression.rs +329 -0
  78. data/ext/itsi_server/src/server/middleware_stack/middlewares/cors.rs +300 -0
  79. data/ext/itsi_server/src/server/middleware_stack/middlewares/csp.rs +193 -0
  80. data/ext/itsi_server/src/server/middleware_stack/middlewares/deny_list.rs +64 -0
  81. data/ext/itsi_server/src/server/middleware_stack/middlewares/error_response/default_responses.rs +188 -0
  82. data/ext/itsi_server/src/server/middleware_stack/middlewares/error_response.rs +168 -0
  83. data/ext/itsi_server/src/server/middleware_stack/middlewares/etag.rs +183 -0
  84. data/ext/itsi_server/src/server/middleware_stack/middlewares/header_interpretation.rs +82 -0
  85. data/ext/itsi_server/src/server/middleware_stack/middlewares/intrusion_protection.rs +209 -0
  86. data/ext/itsi_server/src/server/middleware_stack/middlewares/log_requests.rs +133 -0
  87. data/ext/itsi_server/src/server/middleware_stack/middlewares/max_body.rs +47 -0
  88. data/ext/itsi_server/src/server/middleware_stack/middlewares/mod.rs +122 -0
  89. data/ext/itsi_server/src/server/middleware_stack/middlewares/proxy.rs +407 -0
  90. data/ext/itsi_server/src/server/middleware_stack/middlewares/rate_limit.rs +155 -0
  91. data/ext/itsi_server/src/server/middleware_stack/middlewares/redirect.rs +54 -0
  92. data/ext/itsi_server/src/server/middleware_stack/middlewares/request_headers.rs +54 -0
  93. data/ext/itsi_server/src/server/middleware_stack/middlewares/response_headers.rs +51 -0
  94. data/ext/itsi_server/src/server/middleware_stack/middlewares/ruby_app.rs +138 -0
  95. data/ext/itsi_server/src/server/middleware_stack/middlewares/static_assets.rs +269 -0
  96. data/ext/itsi_server/src/server/middleware_stack/middlewares/static_response.rs +62 -0
  97. data/ext/itsi_server/src/server/middleware_stack/middlewares/string_rewrite.rs +218 -0
  98. data/ext/itsi_server/src/server/middleware_stack/middlewares/token_source.rs +31 -0
  99. data/ext/itsi_server/src/server/middleware_stack/mod.rs +381 -0
  100. data/ext/itsi_server/src/server/mod.rs +14 -0
  101. data/ext/itsi_server/src/server/process_worker.rs +247 -0
  102. data/ext/itsi_server/src/server/redirect_type.rs +26 -0
  103. data/ext/itsi_server/src/server/request_job.rs +11 -0
  104. data/ext/itsi_server/src/server/serve_strategy/acceptor.rs +100 -0
  105. data/ext/itsi_server/src/server/serve_strategy/cluster_mode.rs +411 -0
  106. data/ext/itsi_server/src/server/serve_strategy/mod.rs +31 -0
  107. data/ext/itsi_server/src/server/serve_strategy/single_mode.rs +449 -0
  108. data/ext/itsi_server/src/server/signal.rs +129 -0
  109. data/ext/itsi_server/src/server/size_limited_incoming.rs +107 -0
  110. data/ext/itsi_server/src/server/thread_worker.rs +504 -0
  111. data/ext/itsi_server/src/services/cache_store.rs +74 -0
  112. data/ext/itsi_server/src/services/itsi_http_service.rs +270 -0
  113. data/ext/itsi_server/src/services/mime_types.rs +2896 -0
  114. data/ext/itsi_server/src/services/mod.rs +6 -0
  115. data/ext/itsi_server/src/services/password_hasher.rs +89 -0
  116. data/ext/itsi_server/src/services/rate_limiter.rs +609 -0
  117. data/ext/itsi_server/src/services/static_file_server.rs +1400 -0
  118. data/ext/itsi_tracing/Cargo.lock +274 -0
  119. data/ext/itsi_tracing/Cargo.toml +17 -0
  120. data/ext/itsi_tracing/src/lib.rs +370 -0
  121. data/itsi-scheduler-100.png +0 -0
  122. data/lib/itsi/schedule_refinement.rb +96 -0
  123. data/lib/itsi/scheduler/3.1/itsi_scheduler.so +0 -0
  124. data/lib/itsi/scheduler/3.2/itsi_scheduler.so +0 -0
  125. data/lib/itsi/scheduler/3.3/itsi_scheduler.so +0 -0
  126. data/lib/itsi/scheduler/3.4/itsi_scheduler.so +0 -0
  127. data/lib/itsi/scheduler/4.0/itsi_scheduler.so +0 -0
  128. data/lib/itsi/scheduler/native_extension.rb +34 -0
  129. data/lib/itsi/scheduler/version.rb +7 -0
  130. data/lib/itsi/scheduler.rb +153 -0
  131. data/vendor/rb-sys-build/.cargo-ok +1 -0
  132. data/vendor/rb-sys-build/.cargo_vcs_info.json +6 -0
  133. data/vendor/rb-sys-build/Cargo.lock +294 -0
  134. data/vendor/rb-sys-build/Cargo.toml +71 -0
  135. data/vendor/rb-sys-build/Cargo.toml.orig +32 -0
  136. data/vendor/rb-sys-build/LICENSE-APACHE +190 -0
  137. data/vendor/rb-sys-build/LICENSE-MIT +21 -0
  138. data/vendor/rb-sys-build/src/bindings/sanitizer.rs +185 -0
  139. data/vendor/rb-sys-build/src/bindings/stable_api.rs +247 -0
  140. data/vendor/rb-sys-build/src/bindings/wrapper.h +71 -0
  141. data/vendor/rb-sys-build/src/bindings.rs +280 -0
  142. data/vendor/rb-sys-build/src/cc.rs +421 -0
  143. data/vendor/rb-sys-build/src/lib.rs +12 -0
  144. data/vendor/rb-sys-build/src/rb_config/flags.rs +101 -0
  145. data/vendor/rb-sys-build/src/rb_config/library.rs +132 -0
  146. data/vendor/rb-sys-build/src/rb_config/search_path.rs +57 -0
  147. data/vendor/rb-sys-build/src/rb_config.rs +906 -0
  148. data/vendor/rb-sys-build/src/utils.rs +53 -0
  149. metadata +210 -0
@@ -0,0 +1,320 @@
1
+ mod io_helpers;
2
+ mod io_waiter;
3
+ mod timer;
4
+ use io_helpers::{build_interest, poll_readiness, set_nonblocking};
5
+ use io_waiter::IoWaiter;
6
+ use itsi_error::ItsiError;
7
+ use itsi_rb_helpers::{call_without_gvl, create_ruby_thread};
8
+ use magnus::{
9
+ error::Result as MagnusResult,
10
+ value::{InnerValue, Lazy, LazyId, Opaque, ReprValue},
11
+ Module, RClass, Ruby, Value,
12
+ };
13
+ use mio::{Events, Poll, Token, Waker};
14
+ use parking_lot::{Mutex, RwLock};
15
+ use std::{
16
+ collections::{BinaryHeap, HashMap, VecDeque},
17
+ os::fd::RawFd,
18
+ sync::Arc,
19
+ time::Duration,
20
+ };
21
+ use timer::Timer;
22
+ use tracing::{debug, error, info, warn};
23
+
24
+ #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
25
+ pub(crate) struct Readiness(i16);
26
+
27
+ impl std::fmt::Debug for ItsiScheduler {
28
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
29
+ f.debug_struct("ItsiScheduler").finish()
30
+ }
31
+ }
32
+
33
+ const WAKE_TOKEN: Token = Token(0);
34
+ static ID_CURRENT: LazyId = LazyId::new("current");
35
+ static CLASS_FIBER: Lazy<RClass> =
36
+ Lazy::new(|ruby| ruby.module_kernel().const_get("Fiber").unwrap());
37
+
38
+ #[magnus::wrap(class = "Itsi::Scheduler", free_immediately, size)]
39
+ pub(crate) struct ItsiScheduler {
40
+ timers: Mutex<BinaryHeap<Timer>>,
41
+ io_waiters: Mutex<HashMap<Token, IoWaiter>>,
42
+ registry: Mutex<HashMap<RawFd, VecDeque<IoWaiter>>>,
43
+ poll: Mutex<Poll>,
44
+ events: Mutex<Events>,
45
+ waker: Mutex<Waker>,
46
+ }
47
+
48
+ impl Default for ItsiScheduler {
49
+ fn default() -> Self {
50
+ let poll = Poll::new().unwrap();
51
+ let waker = Waker::new(poll.registry(), WAKE_TOKEN).unwrap();
52
+ let events = Events::with_capacity(1024);
53
+
54
+ ItsiScheduler {
55
+ timers: Mutex::new(BinaryHeap::new()),
56
+ io_waiters: Mutex::new(HashMap::new()),
57
+ registry: Mutex::new(HashMap::new()),
58
+ poll: Mutex::new(poll),
59
+ events: Mutex::new(events),
60
+ waker: Mutex::new(waker),
61
+ }
62
+ }
63
+ }
64
+
65
+ impl ItsiScheduler {
66
+ pub fn initialize(&self) {}
67
+
68
+ pub fn wake(&self) -> MagnusResult<()> {
69
+ self.waker.lock().wake().map_err(|_| {
70
+ magnus::Error::new(
71
+ magnus::Ruby::get().unwrap().exception_standard_error(),
72
+ "Failed to wake the scheduler",
73
+ )
74
+ })?;
75
+ Ok(())
76
+ }
77
+ pub fn register_io_wait(
78
+ &self,
79
+ io_obj: i32,
80
+ events: i16,
81
+ timeout: Option<f64>,
82
+ token: usize,
83
+ ) -> MagnusResult<Option<i16>> {
84
+ debug!(
85
+ "Registering IO Wait for {:?}, {:?}, {:?}, {:?}",
86
+ io_obj, events, timeout, token
87
+ );
88
+ let fd: RawFd = io_obj;
89
+
90
+ let readiness = poll_readiness(fd, events).unwrap_or(Readiness(0));
91
+ if readiness == Readiness(events) {
92
+ return Ok(Some(readiness.0));
93
+ }
94
+
95
+ set_nonblocking(fd)?;
96
+ let interest = build_interest(events)?;
97
+ let token = Token(token);
98
+ let mut waiter = IoWaiter::new(fd, events, token);
99
+ self.io_waiters.lock().insert(token, waiter.clone());
100
+ let mut binding = self.registry.lock();
101
+ let queue = binding.entry(fd).or_default();
102
+
103
+ queue.push_back(waiter.clone());
104
+
105
+ if queue.len() == 1 {
106
+ self.poll
107
+ .lock()
108
+ .registry()
109
+ .register(&mut waiter, token, interest)
110
+ .map_err(|e| ItsiError::ArgumentError(format!("register error: {}", e)))?;
111
+ }
112
+ Ok(None)
113
+ }
114
+
115
+ pub fn start_timer(&self, timeout: Option<f64>, token: usize) {
116
+ if timeout.is_some_and(|t| t >= 0.0) {
117
+ let timer_entry = Timer::new(Duration::from_secs_f64(timeout.unwrap()), Token(token));
118
+ self.timers.lock().push(timer_entry);
119
+ }
120
+ }
121
+
122
+ pub fn clear_timer(&self, token: usize) {
123
+ self.timers.lock().retain(|timer| timer.token.0 != token);
124
+ }
125
+
126
+ pub fn has_pending_io(&self) -> bool {
127
+ !self.timers.lock().is_empty() || !self.io_waiters.lock().is_empty()
128
+ }
129
+
130
+ pub fn class_info(msg: String) {
131
+ info!(msg);
132
+ }
133
+
134
+ pub fn info(&self, msg: String) {
135
+ info!(msg);
136
+ }
137
+
138
+ pub fn warn(&self, msg: String) {
139
+ warn!(msg);
140
+ }
141
+
142
+ pub fn debug(&self, msg: String) {
143
+ debug!(msg);
144
+ }
145
+
146
+ pub fn fetch_due_events(&self) -> MagnusResult<Option<Vec<(usize, i16)>>> {
147
+ call_without_gvl(|| {
148
+ let timeout = if let Some(timer) = self.timers.lock().peek() {
149
+ timer.duration().or(Some(Duration::ZERO))
150
+ } else {
151
+ None
152
+ };
153
+ let mut due_fibers: Option<Vec<(usize, i16)>> = None;
154
+ let mut io_waiters = self.io_waiters.lock();
155
+ if !io_waiters.is_empty() || timeout.is_none() {
156
+ let mut events = self.events.lock();
157
+ {
158
+ let mut poll = self.poll.lock();
159
+ if let Err(_err) = poll.poll(&mut events, timeout) {
160
+ return Ok(due_fibers);
161
+ }
162
+ };
163
+
164
+ for event in events.iter() {
165
+ let token = event.token();
166
+ if token == WAKE_TOKEN {
167
+ continue;
168
+ }
169
+
170
+ let waiter = io_waiters.remove(&token);
171
+ if waiter.is_none() {
172
+ continue;
173
+ }
174
+ let mut waiter = waiter.unwrap();
175
+ let mut evt_readiness = 0;
176
+ if event.is_readable() {
177
+ evt_readiness |= 1;
178
+ }
179
+ if event.is_priority() {
180
+ evt_readiness |= 2;
181
+ }
182
+ if event.is_writable() {
183
+ evt_readiness |= 4
184
+ }
185
+ self.poll
186
+ .lock()
187
+ .registry()
188
+ .deregister(&mut waiter)
189
+ .map_err(|_| {
190
+ ItsiError::ArgumentError("Failed to deregister".to_string())
191
+ })?;
192
+
193
+ due_fibers
194
+ .get_or_insert_default()
195
+ .push((waiter.token.0, evt_readiness));
196
+
197
+ let mut binding = self.registry.lock();
198
+ // Pop the current item for the current waiter off the queue
199
+ let queue = binding.get_mut(&(waiter.fd)).unwrap();
200
+ queue.pop_front();
201
+
202
+ if let Some(head) = queue.get_mut(0) {
203
+ // Register the next item in the queue if there is one.
204
+ let interest = build_interest(head.readiness)?;
205
+ self.poll
206
+ .lock()
207
+ .registry()
208
+ .register(head, head.token, interest)
209
+ .map_err(|_| {
210
+ ItsiError::ArgumentError("Failed to deregister".to_string())
211
+ })?;
212
+ } else {
213
+ // Otherwise we drop the queue altogether.
214
+ binding.remove(&waiter.fd);
215
+ }
216
+ }
217
+ return Ok(due_fibers);
218
+ }
219
+ Ok(None)
220
+ })
221
+ }
222
+
223
+ pub fn run_blocking_in_thread<T, F>(&self, ruby: &Ruby, work: F) -> MagnusResult<Option<T>>
224
+ where
225
+ T: Send + Sync + std::fmt::Debug + 'static,
226
+ F: FnOnce() -> Option<T> + Send + 'static,
227
+ {
228
+ let result: Arc<RwLock<Option<T>>> = Arc::new(RwLock::new(None));
229
+ let result_clone = Arc::clone(&result);
230
+
231
+ let class_fiber = ruby.get_inner(&CLASS_FIBER);
232
+ let current_fiber = ruby
233
+ .get_inner(&CLASS_FIBER)
234
+ .funcall::<_, _, Value>(*ID_CURRENT, ());
235
+
236
+ if current_fiber.is_err() {
237
+ error!("Failed to get current fiber");
238
+ return Err(ItsiError::ArgumentError("Failed to get current fiber".to_string()).into());
239
+ }
240
+ let current_fiber = Opaque::from(current_fiber.unwrap());
241
+ let scheduler = Opaque::from(class_fiber.funcall::<_, _, Value>("scheduler", ()).unwrap());
242
+
243
+ create_ruby_thread(move || {
244
+ call_without_gvl(|| {
245
+ let outcome = work();
246
+ *result_clone.write() = outcome;
247
+ });
248
+
249
+ let ruby = Ruby::get().unwrap();
250
+ scheduler
251
+ .get_inner_with(&ruby)
252
+ .funcall::<_, _, Value>("unblock", (None::<String>, current_fiber))
253
+ .unwrap();
254
+ });
255
+
256
+ scheduler
257
+ .get_inner_with(ruby)
258
+ .funcall::<_, _, Value>("block", (None::<Value>, None::<u64>))?;
259
+
260
+ let result_opt = Arc::try_unwrap(result).unwrap().write().take();
261
+ Ok(result_opt)
262
+ }
263
+
264
+ pub fn address_resolve(
265
+ ruby: &Ruby,
266
+ rself: &Self,
267
+ hostname: String,
268
+ ) -> MagnusResult<Option<Vec<String>>> {
269
+ let result: Option<Vec<String>> = rself.run_blocking_in_thread(ruby, move || {
270
+ use std::net::ToSocketAddrs;
271
+ let addrs_res = (hostname.as_str(), 0).to_socket_addrs();
272
+ match addrs_res {
273
+ Ok(addrs) => {
274
+ let ips: Vec<String> = addrs.map(|s| s.ip().to_string()).collect();
275
+ Some(ips)
276
+ }
277
+ Err(_) => None,
278
+ }
279
+ })?;
280
+ Ok(result)
281
+ }
282
+
283
+ pub fn fetch_due_timers(&self) -> MagnusResult<Option<Vec<usize>>> {
284
+ call_without_gvl(|| {
285
+ let mut timers = self.timers.lock();
286
+ let mut io_waiters = self.io_waiters.lock();
287
+ let mut due_fibers: Option<Vec<usize>> = None;
288
+ while let Some(timer) = timers.peek() {
289
+ if timer.is_due() {
290
+ due_fibers.get_or_insert_default().push(timer.token.0);
291
+ if let Some(waiter) = io_waiters.remove(&timer.token) {
292
+ let mut binding = self.registry.lock();
293
+ // Pop the current item for the current waiter off the queue
294
+ let queue = binding.get_mut(&waiter.fd).unwrap();
295
+ queue.pop_front();
296
+
297
+ if let Some(head) = queue.get_mut(0) {
298
+ // Register the next item in the queue if there is one.
299
+ let interest = build_interest(head.readiness)?;
300
+ self.poll
301
+ .lock()
302
+ .registry()
303
+ .register(head, head.token, interest)
304
+ .map_err(|_| {
305
+ ItsiError::ArgumentError("Failed to deregister".to_string())
306
+ })?;
307
+ } else {
308
+ // Otherwise we drop the queue altogether.
309
+ binding.remove(&waiter.fd);
310
+ }
311
+ }
312
+ timers.pop();
313
+ } else {
314
+ break;
315
+ }
316
+ }
317
+ Ok(due_fibers)
318
+ })
319
+ }
320
+ }
@@ -0,0 +1,39 @@
1
+ use itsi_scheduler::ItsiScheduler;
2
+ use magnus::{function, method, Class, Error, Module, Object, Ruby};
3
+ mod itsi_scheduler;
4
+
5
+ #[magnus::init]
6
+ fn init(ruby: &Ruby) -> Result<(), Error> {
7
+ itsi_tracing::init();
8
+ let module = ruby.define_module("Itsi")?;
9
+ let scheduler = module.define_class("Scheduler", ruby.class_object())?;
10
+ scheduler.define_singleton_method("info", function!(ItsiScheduler::class_info, 1))?;
11
+ scheduler.define_alloc_func::<ItsiScheduler>();
12
+ scheduler.define_method("initialize", method!(ItsiScheduler::initialize, 0))?;
13
+ scheduler.define_method("wake", method!(ItsiScheduler::wake, 0))?;
14
+ scheduler.define_method(
15
+ "register_io_wait",
16
+ method!(ItsiScheduler::register_io_wait, 4),
17
+ )?;
18
+ scheduler.define_method("info", method!(ItsiScheduler::info, 1))?;
19
+ scheduler.define_method("debug", method!(ItsiScheduler::debug, 1))?;
20
+ scheduler.define_method("warn", method!(ItsiScheduler::warn, 1))?;
21
+ scheduler.define_method("start_timer", method!(ItsiScheduler::start_timer, 2))?;
22
+ scheduler.define_method("clear_timer", method!(ItsiScheduler::clear_timer, 1))?;
23
+ scheduler.define_method(
24
+ "address_resolve",
25
+ method!(ItsiScheduler::address_resolve, 1),
26
+ )?;
27
+ scheduler.define_method("has_pending_io?", method!(ItsiScheduler::has_pending_io, 0))?;
28
+
29
+ scheduler.define_method(
30
+ "fetch_due_timers",
31
+ method!(ItsiScheduler::fetch_due_timers, 0),
32
+ )?;
33
+ scheduler.define_method(
34
+ "fetch_due_events",
35
+ method!(ItsiScheduler::fetch_due_events, 0),
36
+ )?;
37
+
38
+ Ok(())
39
+ }