itsi-scheduler 0.1.11 → 0.1.12
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/CODE_OF_CONDUCT.md +7 -0
- data/Cargo.lock +75 -14
- data/README.md +5 -0
- data/_index.md +7 -0
- data/ext/itsi_error/src/lib.rs +9 -0
- data/ext/itsi_error/target/debug/build/clang-sys-da71b0344e568175/out/common.rs +355 -0
- data/ext/itsi_error/target/debug/build/clang-sys-da71b0344e568175/out/dynamic.rs +276 -0
- data/ext/itsi_error/target/debug/build/clang-sys-da71b0344e568175/out/macros.rs +49 -0
- data/ext/itsi_error/target/debug/build/rb-sys-49f554618693db24/out/bindings-0.9.110-mri-arm64-darwin23-3.4.2.rs +8865 -0
- data/ext/itsi_error/target/debug/incremental/itsi_error-1mmt5sux7jb0i/s-h510z7m8v9-0bxu7yd.lock +0 -0
- data/ext/itsi_error/target/debug/incremental/itsi_error-2vn3jey74oiw0/s-h5113n0e7e-1v5qzs6.lock +0 -0
- data/ext/itsi_error/target/debug/incremental/itsi_error-37uv9dicz7awp/s-h510ykifhe-0tbnep2.lock +0 -0
- data/ext/itsi_error/target/debug/incremental/itsi_error-37uv9dicz7awp/s-h510yyocpj-0tz7ug7.lock +0 -0
- data/ext/itsi_error/target/debug/incremental/itsi_error-37uv9dicz7awp/s-h510z0xc8g-14ol18k.lock +0 -0
- data/ext/itsi_error/target/debug/incremental/itsi_error-3g5qf4y7d54uj/s-h5113n0e7d-1trk8on.lock +0 -0
- data/ext/itsi_error/target/debug/incremental/itsi_error-3lpfftm45d3e2/s-h510z7m8r3-1pxp20o.lock +0 -0
- data/ext/itsi_error/target/debug/incremental/itsi_error-3o4qownhl3d7n/s-h510ykifek-1uxasnk.lock +0 -0
- data/ext/itsi_error/target/debug/incremental/itsi_error-3o4qownhl3d7n/s-h510yyocki-11u37qm.lock +0 -0
- data/ext/itsi_error/target/debug/incremental/itsi_error-3o4qownhl3d7n/s-h510z0xc93-0pmy0zm.lock +0 -0
- data/ext/itsi_rb_helpers/Cargo.toml +1 -0
- data/ext/itsi_rb_helpers/src/heap_value.rs +18 -0
- data/ext/itsi_rb_helpers/src/lib.rs +34 -7
- data/ext/itsi_rb_helpers/target/debug/build/clang-sys-da71b0344e568175/out/common.rs +355 -0
- data/ext/itsi_rb_helpers/target/debug/build/clang-sys-da71b0344e568175/out/dynamic.rs +276 -0
- data/ext/itsi_rb_helpers/target/debug/build/clang-sys-da71b0344e568175/out/macros.rs +49 -0
- data/ext/itsi_rb_helpers/target/debug/build/rb-sys-eb9ed4ff3a60f995/out/bindings-0.9.110-mri-arm64-darwin23-3.4.2.rs +8865 -0
- data/ext/itsi_rb_helpers/target/debug/incremental/itsi_rb_helpers-040pxg6yhb3g3/s-h5113n7a1b-03bwlt4.lock +0 -0
- data/ext/itsi_rb_helpers/target/debug/incremental/itsi_rb_helpers-131g1u4dzkt1a/s-h51113xnh3-1eik1ip.lock +0 -0
- data/ext/itsi_rb_helpers/target/debug/incremental/itsi_rb_helpers-131g1u4dzkt1a/s-h5111704jj-0g4rj8x.lock +0 -0
- data/ext/itsi_rb_helpers/target/debug/incremental/itsi_rb_helpers-1q2d3drtxrzs5/s-h5113n79yl-0bxcqc5.lock +0 -0
- data/ext/itsi_rb_helpers/target/debug/incremental/itsi_rb_helpers-374a9h7ovycj0/s-h51113xoox-10de2hp.lock +0 -0
- data/ext/itsi_rb_helpers/target/debug/incremental/itsi_rb_helpers-374a9h7ovycj0/s-h5111704w7-0vdq7gq.lock +0 -0
- data/ext/itsi_server/Cargo.toml +69 -30
- data/ext/itsi_server/src/lib.rs +79 -147
- data/ext/itsi_server/src/{body_proxy → ruby_types/itsi_body_proxy}/big_bytes.rs +10 -5
- data/ext/itsi_server/src/{body_proxy/itsi_body_proxy.rs → ruby_types/itsi_body_proxy/mod.rs} +22 -3
- data/ext/itsi_server/src/ruby_types/itsi_grpc_request.rs +147 -0
- data/ext/itsi_server/src/ruby_types/itsi_grpc_response.rs +19 -0
- data/ext/itsi_server/src/ruby_types/itsi_grpc_stream/mod.rs +216 -0
- data/ext/itsi_server/src/{request/itsi_request.rs → ruby_types/itsi_http_request.rs} +101 -117
- data/ext/itsi_server/src/{response/itsi_response.rs → ruby_types/itsi_http_response.rs} +72 -41
- data/ext/itsi_server/src/ruby_types/itsi_server/file_watcher.rs +225 -0
- data/ext/itsi_server/src/ruby_types/itsi_server/itsi_server_config.rs +355 -0
- data/ext/itsi_server/src/ruby_types/itsi_server.rs +82 -0
- data/ext/itsi_server/src/ruby_types/mod.rs +55 -0
- data/ext/itsi_server/src/server/bind.rs +13 -5
- data/ext/itsi_server/src/server/byte_frame.rs +32 -0
- data/ext/itsi_server/src/server/cache_store.rs +74 -0
- data/ext/itsi_server/src/server/itsi_service.rs +172 -0
- data/ext/itsi_server/src/server/lifecycle_event.rs +3 -0
- data/ext/itsi_server/src/server/listener.rs +102 -2
- data/ext/itsi_server/src/server/middleware_stack/middleware.rs +153 -0
- data/ext/itsi_server/src/server/middleware_stack/middlewares/allow_list.rs +47 -0
- data/ext/itsi_server/src/server/middleware_stack/middlewares/auth_api_key.rs +58 -0
- data/ext/itsi_server/src/server/middleware_stack/middlewares/auth_basic.rs +82 -0
- data/ext/itsi_server/src/server/middleware_stack/middlewares/auth_jwt.rs +321 -0
- data/ext/itsi_server/src/server/middleware_stack/middlewares/cache_control.rs +139 -0
- data/ext/itsi_server/src/server/middleware_stack/middlewares/compression.rs +300 -0
- data/ext/itsi_server/src/server/middleware_stack/middlewares/cors.rs +287 -0
- data/ext/itsi_server/src/server/middleware_stack/middlewares/deny_list.rs +48 -0
- data/ext/itsi_server/src/server/middleware_stack/middlewares/error_response.rs +127 -0
- data/ext/itsi_server/src/server/middleware_stack/middlewares/etag.rs +191 -0
- data/ext/itsi_server/src/server/middleware_stack/middlewares/grpc_service.rs +72 -0
- data/ext/itsi_server/src/server/middleware_stack/middlewares/header_interpretation.rs +85 -0
- data/ext/itsi_server/src/server/middleware_stack/middlewares/intrusion_protection.rs +195 -0
- data/ext/itsi_server/src/server/middleware_stack/middlewares/log_requests.rs +82 -0
- data/ext/itsi_server/src/server/middleware_stack/middlewares/mod.rs +82 -0
- data/ext/itsi_server/src/server/middleware_stack/middlewares/proxy.rs +216 -0
- data/ext/itsi_server/src/server/middleware_stack/middlewares/rate_limit.rs +124 -0
- data/ext/itsi_server/src/server/middleware_stack/middlewares/redirect.rs +76 -0
- data/ext/itsi_server/src/server/middleware_stack/middlewares/request_headers.rs +43 -0
- data/ext/itsi_server/src/server/middleware_stack/middlewares/response_headers.rs +34 -0
- data/ext/itsi_server/src/server/middleware_stack/middlewares/ruby_app.rs +93 -0
- data/ext/itsi_server/src/server/middleware_stack/middlewares/static_assets.rs +162 -0
- data/ext/itsi_server/src/server/middleware_stack/middlewares/string_rewrite.rs +158 -0
- data/ext/itsi_server/src/server/middleware_stack/middlewares/token_source.rs +12 -0
- data/ext/itsi_server/src/server/middleware_stack/mod.rs +315 -0
- data/ext/itsi_server/src/server/mod.rs +8 -1
- data/ext/itsi_server/src/server/process_worker.rs +38 -12
- data/ext/itsi_server/src/server/rate_limiter.rs +565 -0
- data/ext/itsi_server/src/server/request_job.rs +11 -0
- data/ext/itsi_server/src/server/serve_strategy/cluster_mode.rs +119 -42
- data/ext/itsi_server/src/server/serve_strategy/mod.rs +9 -6
- data/ext/itsi_server/src/server/serve_strategy/single_mode.rs +256 -111
- data/ext/itsi_server/src/server/signal.rs +19 -0
- data/ext/itsi_server/src/server/static_file_server.rs +984 -0
- data/ext/itsi_server/src/server/thread_worker.rs +139 -94
- data/ext/itsi_server/src/server/types.rs +43 -0
- data/ext/itsi_tracing/Cargo.toml +1 -0
- data/ext/itsi_tracing/src/lib.rs +216 -45
- data/ext/itsi_tracing/target/debug/incremental/itsi_tracing-0994n8rpvvt9m/s-h510hfz1f6-1kbycmq.lock +0 -0
- data/ext/itsi_tracing/target/debug/incremental/itsi_tracing-0bob7bf4yq34i/s-h5113125h5-0lh4rag.lock +0 -0
- data/ext/itsi_tracing/target/debug/incremental/itsi_tracing-2fcodulrxbbxo/s-h510h2infk-0hp5kjw.lock +0 -0
- data/ext/itsi_tracing/target/debug/incremental/itsi_tracing-2iak63r1woi1l/s-h510h2in4q-0kxfzw1.lock +0 -0
- data/ext/itsi_tracing/target/debug/incremental/itsi_tracing-2kk4qj9gn5dg2/s-h5113124kv-0enwon2.lock +0 -0
- data/ext/itsi_tracing/target/debug/incremental/itsi_tracing-2mwo0yas7dtw4/s-h510hfz1ha-1udgpei.lock +0 -0
- data/lib/itsi/scheduler/version.rb +1 -1
- data/lib/itsi/scheduler.rb +2 -2
- metadata +77 -12
- data/ext/itsi_server/extconf.rb +0 -6
- data/ext/itsi_server/src/body_proxy/mod.rs +0 -2
- data/ext/itsi_server/src/request/mod.rs +0 -1
- data/ext/itsi_server/src/response/mod.rs +0 -1
- data/ext/itsi_server/src/server/itsi_server.rs +0 -288
@@ -1,9 +1,8 @@
|
|
1
|
-
use
|
2
|
-
use crate::{request::itsi_request::ItsiRequest, ITSI_SERVER};
|
1
|
+
use async_channel::Sender;
|
3
2
|
use itsi_rb_helpers::{
|
4
|
-
call_with_gvl, call_without_gvl, create_ruby_thread, kill_threads,
|
3
|
+
call_with_gvl, call_without_gvl, create_ruby_thread, kill_threads, HeapValue,
|
5
4
|
};
|
6
|
-
use itsi_tracing::{debug, error,
|
5
|
+
use itsi_tracing::{debug, error, warn};
|
7
6
|
use magnus::{
|
8
7
|
error::Result,
|
9
8
|
value::{InnerValue, Lazy, LazyId, Opaque, ReprValue},
|
@@ -15,26 +14,34 @@ use std::{
|
|
15
14
|
num::NonZeroU8,
|
16
15
|
ops::Deref,
|
17
16
|
sync::{
|
18
|
-
atomic::{AtomicBool, Ordering},
|
17
|
+
atomic::{AtomicBool, AtomicU64, Ordering},
|
19
18
|
Arc,
|
20
19
|
},
|
21
20
|
thread,
|
22
|
-
time::{Duration, Instant},
|
21
|
+
time::{Duration, Instant, SystemTime, UNIX_EPOCH},
|
23
22
|
};
|
24
23
|
use tokio::{runtime::Builder as RuntimeBuilder, sync::watch};
|
25
24
|
use tracing::instrument;
|
25
|
+
|
26
|
+
use crate::ruby_types::{
|
27
|
+
itsi_grpc_request::ItsiGrpcRequest, itsi_http_request::ItsiHttpRequest,
|
28
|
+
itsi_server::itsi_server_config::ServerParams, ITSI_SERVER,
|
29
|
+
};
|
30
|
+
|
31
|
+
use super::request_job::RequestJob;
|
26
32
|
pub struct ThreadWorker {
|
27
|
-
pub
|
28
|
-
pub id:
|
29
|
-
pub
|
33
|
+
pub params: Arc<ServerParams>,
|
34
|
+
pub id: u8,
|
35
|
+
pub name: String,
|
36
|
+
pub request_id: AtomicU64,
|
37
|
+
pub current_request_start: AtomicU64,
|
30
38
|
pub receiver: Arc<async_channel::Receiver<RequestJob>>,
|
31
|
-
pub sender:
|
39
|
+
pub sender: Sender<RequestJob>,
|
32
40
|
pub thread: RwLock<Option<HeapValue<Thread>>>,
|
33
41
|
pub terminated: Arc<AtomicBool>,
|
34
42
|
pub scheduler_class: Option<Opaque<Value>>,
|
35
43
|
}
|
36
44
|
|
37
|
-
static ID_CALL: LazyId = LazyId::new("call");
|
38
45
|
static ID_ALIVE: LazyId = LazyId::new("alive?");
|
39
46
|
static ID_SCHEDULER: LazyId = LazyId::new("scheduler");
|
40
47
|
static ID_SCHEDULE: LazyId = LazyId::new("schedule");
|
@@ -48,28 +55,26 @@ static CLASS_FIBER: Lazy<RClass> = Lazy::new(|ruby| {
|
|
48
55
|
});
|
49
56
|
|
50
57
|
pub struct TerminateWakerSignal(bool);
|
58
|
+
type ThreadWorkerBuildResult = Result<(Arc<Vec<Arc<ThreadWorker>>>, Sender<RequestJob>)>;
|
51
59
|
|
52
|
-
#[instrument(name = "
|
60
|
+
#[instrument(name = "boot", parent=None, skip(params, threads, pid))]
|
53
61
|
pub fn build_thread_workers(
|
54
|
-
|
62
|
+
params: Arc<ServerParams>,
|
55
63
|
pid: Pid,
|
56
64
|
threads: NonZeroU8,
|
57
|
-
|
58
|
-
|
59
|
-
) -> Result<(Arc<Vec<ThreadWorker>>, async_channel::Sender<RequestJob>)> {
|
60
|
-
let (sender, receiver) = async_channel::bounded(20);
|
65
|
+
) -> ThreadWorkerBuildResult {
|
66
|
+
let (sender, receiver) = async_channel::bounded((threads.get() as u16 * 30) as usize);
|
61
67
|
let receiver_ref = Arc::new(receiver);
|
62
68
|
let sender_ref = sender;
|
63
|
-
let
|
69
|
+
let scheduler_class = load_scheduler_class(params.scheduler_class.clone())?;
|
64
70
|
Ok((
|
65
71
|
Arc::new(
|
66
72
|
(1..=u8::from(threads))
|
67
73
|
.map(|id| {
|
68
|
-
info!(pid = pid.as_raw(), id, "Thread");
|
69
74
|
ThreadWorker::new(
|
70
|
-
|
75
|
+
params.clone(),
|
76
|
+
id,
|
71
77
|
format!("{:?}#{:?}", pid, id),
|
72
|
-
app,
|
73
78
|
receiver_ref.clone(),
|
74
79
|
sender_ref.clone(),
|
75
80
|
scheduler_class,
|
@@ -81,12 +86,8 @@ pub fn build_thread_workers(
|
|
81
86
|
))
|
82
87
|
}
|
83
88
|
|
84
|
-
pub fn
|
85
|
-
app: HeapVal,
|
86
|
-
scheduler_class: Option<String>,
|
87
|
-
) -> Result<(Opaque<Value>, Option<Opaque<Value>>)> {
|
89
|
+
pub fn load_scheduler_class(scheduler_class: Option<String>) -> Result<Option<Opaque<Value>>> {
|
88
90
|
call_with_gvl(|ruby| {
|
89
|
-
let app = Opaque::from(app.funcall::<_, _, Value>(*ID_CALL, ())?);
|
90
91
|
let scheduler_class = if let Some(scheduler_class) = scheduler_class {
|
91
92
|
Some(Opaque::from(
|
92
93
|
ruby.module_kernel()
|
@@ -95,76 +96,67 @@ pub fn load_app(
|
|
95
96
|
} else {
|
96
97
|
None
|
97
98
|
};
|
98
|
-
Ok(
|
99
|
+
Ok(scheduler_class)
|
99
100
|
})
|
100
101
|
}
|
101
102
|
impl ThreadWorker {
|
102
103
|
pub fn new(
|
103
|
-
|
104
|
-
id:
|
105
|
-
|
104
|
+
params: Arc<ServerParams>,
|
105
|
+
id: u8,
|
106
|
+
name: String,
|
106
107
|
receiver: Arc<async_channel::Receiver<RequestJob>>,
|
107
|
-
sender:
|
108
|
+
sender: Sender<RequestJob>,
|
108
109
|
scheduler_class: Option<Opaque<Value>>,
|
109
|
-
) -> Result<Self
|
110
|
-
let
|
111
|
-
|
110
|
+
) -> Result<Arc<Self>> {
|
111
|
+
let worker = Arc::new(Self {
|
112
|
+
params,
|
112
113
|
id,
|
113
|
-
|
114
|
+
request_id: AtomicU64::new(0),
|
115
|
+
current_request_start: AtomicU64::new(0),
|
116
|
+
name,
|
114
117
|
receiver,
|
115
118
|
sender,
|
116
119
|
thread: RwLock::new(None),
|
117
120
|
terminated: Arc::new(AtomicBool::new(false)),
|
118
121
|
scheduler_class,
|
119
|
-
};
|
120
|
-
worker.run()?;
|
122
|
+
});
|
123
|
+
worker.clone().run()?;
|
121
124
|
Ok(worker)
|
122
125
|
}
|
123
126
|
|
124
|
-
#[instrument(skip(self), fields(id = self.id))]
|
125
|
-
pub async fn request_shutdown(&self) {
|
126
|
-
match self.sender.send(RequestJob::Shutdown).await {
|
127
|
-
Ok(_) => {}
|
128
|
-
Err(err) => error!("Failed to send shutdown request: {}", err),
|
129
|
-
};
|
130
|
-
debug!("Requesting shutdown");
|
131
|
-
}
|
132
|
-
|
133
127
|
#[instrument(skip(self, deadline), fields(id = self.id))]
|
134
128
|
pub fn poll_shutdown(&self, deadline: Instant) -> bool {
|
135
|
-
|
136
|
-
if
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
kill_threads(vec![thread.as_value()]);
|
141
|
-
}
|
142
|
-
if thread.funcall::<_, _, bool>(*ID_ALIVE, ()).unwrap_or(false) {
|
143
|
-
return true;
|
144
|
-
}
|
145
|
-
debug!("Thread has shut down");
|
129
|
+
if let Some(thread) = self.thread.read().deref() {
|
130
|
+
if Instant::now() > deadline {
|
131
|
+
warn!("Worker shutdown timed out. Killing thread");
|
132
|
+
self.terminated.store(true, Ordering::SeqCst);
|
133
|
+
kill_threads(vec![thread.as_value()]);
|
146
134
|
}
|
147
|
-
|
135
|
+
debug!("Checking thread status");
|
136
|
+
if thread.funcall::<_, _, bool>(*ID_ALIVE, ()).unwrap_or(false) {
|
137
|
+
return true;
|
138
|
+
}
|
139
|
+
debug!("Thread has shut down");
|
140
|
+
}
|
141
|
+
self.thread.write().take();
|
148
142
|
|
149
|
-
|
150
|
-
})
|
143
|
+
false
|
151
144
|
}
|
152
145
|
|
153
|
-
pub fn run(
|
154
|
-
let
|
155
|
-
let app = self.app;
|
146
|
+
pub fn run(self: Arc<Self>) -> Result<()> {
|
147
|
+
let name = self.name.clone();
|
156
148
|
let receiver = self.receiver.clone();
|
157
149
|
let terminated = self.terminated.clone();
|
158
150
|
let scheduler_class = self.scheduler_class;
|
159
|
-
let
|
151
|
+
let params = self.params.clone();
|
152
|
+
let self_ref = self.clone();
|
160
153
|
call_with_gvl(|_| {
|
161
154
|
*self.thread.write() = Some(
|
162
155
|
create_ruby_thread(move || {
|
163
156
|
if let Some(scheduler_class) = scheduler_class {
|
164
|
-
if let Err(err) =
|
165
|
-
|
166
|
-
|
167
|
-
app,
|
157
|
+
if let Err(err) = self_ref.fiber_accept_loop(
|
158
|
+
params,
|
159
|
+
name,
|
168
160
|
receiver,
|
169
161
|
scheduler_class,
|
170
162
|
terminated,
|
@@ -172,7 +164,7 @@ impl ThreadWorker {
|
|
172
164
|
error!("Error in fiber_accept_loop: {:?}", err);
|
173
165
|
}
|
174
166
|
} else {
|
175
|
-
|
167
|
+
self_ref.accept_loop(params, name, receiver, terminated);
|
176
168
|
}
|
177
169
|
})
|
178
170
|
.into(),
|
@@ -183,7 +175,7 @@ impl ThreadWorker {
|
|
183
175
|
}
|
184
176
|
|
185
177
|
pub fn build_scheduler_proc(
|
186
|
-
|
178
|
+
self: Arc<Self>,
|
187
179
|
leader: &Arc<Mutex<Option<RequestJob>>>,
|
188
180
|
receiver: &Arc<async_channel::Receiver<RequestJob>>,
|
189
181
|
terminated: &Arc<AtomicBool>,
|
@@ -205,6 +197,7 @@ impl ThreadWorker {
|
|
205
197
|
let receiver = receiver.clone();
|
206
198
|
let terminated = terminated.clone();
|
207
199
|
let waker_sender = waker_sender.clone();
|
200
|
+
let self_ref = self.clone();
|
208
201
|
let mut batch = Vec::with_capacity(MAX_BATCH_SIZE as usize);
|
209
202
|
|
210
203
|
static MAX_BATCH_SIZE: i32 = 25;
|
@@ -212,8 +205,11 @@ impl ThreadWorker {
|
|
212
205
|
let mut idle_counter = 0;
|
213
206
|
if let Some(v) = leader_clone.lock().take() {
|
214
207
|
match v {
|
215
|
-
RequestJob::
|
216
|
-
batch.push(RequestJob::
|
208
|
+
RequestJob::ProcessHttpRequest(itsi_request, app_proc) => {
|
209
|
+
batch.push(RequestJob::ProcessHttpRequest(itsi_request, app_proc))
|
210
|
+
}
|
211
|
+
RequestJob::ProcessGrpcRequest(itsi_request, app_proc) => {
|
212
|
+
batch.push(RequestJob::ProcessGrpcRequest(itsi_request, app_proc))
|
217
213
|
}
|
218
214
|
RequestJob::Shutdown => {
|
219
215
|
waker_sender.send(TerminateWakerSignal(true)).unwrap();
|
@@ -232,12 +228,38 @@ impl ThreadWorker {
|
|
232
228
|
let shutdown_requested = call_with_gvl(|_| {
|
233
229
|
for req in batch.drain(..) {
|
234
230
|
match req {
|
235
|
-
RequestJob::
|
231
|
+
RequestJob::ProcessHttpRequest(request, app_proc) => {
|
232
|
+
self_ref.request_id.fetch_add(1, Ordering::Relaxed);
|
233
|
+
self_ref.current_request_start.store(
|
234
|
+
SystemTime::now()
|
235
|
+
.duration_since(UNIX_EPOCH)
|
236
|
+
.unwrap()
|
237
|
+
.as_secs(),
|
238
|
+
Ordering::Relaxed,
|
239
|
+
);
|
236
240
|
let response = request.response.clone();
|
237
|
-
if let Err(err) =
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
+
if let Err(err) = server.funcall::<_, _, Value>(
|
242
|
+
*ID_SCHEDULE,
|
243
|
+
(app_proc.as_value(), request),
|
244
|
+
) {
|
245
|
+
ItsiHttpRequest::internal_error(ruby, response, err)
|
246
|
+
}
|
247
|
+
}
|
248
|
+
RequestJob::ProcessGrpcRequest(request, app_proc) => {
|
249
|
+
self_ref.request_id.fetch_add(1, Ordering::Relaxed);
|
250
|
+
self_ref.current_request_start.store(
|
251
|
+
SystemTime::now()
|
252
|
+
.duration_since(UNIX_EPOCH)
|
253
|
+
.unwrap()
|
254
|
+
.as_secs(),
|
255
|
+
Ordering::Relaxed,
|
256
|
+
);
|
257
|
+
let response = request.stream.clone();
|
258
|
+
if let Err(err) = server.funcall::<_, _, Value>(
|
259
|
+
*ID_SCHEDULE,
|
260
|
+
(app_proc.as_value(), request),
|
261
|
+
) {
|
262
|
+
ItsiGrpcRequest::internal_error(ruby, response, err)
|
241
263
|
}
|
242
264
|
}
|
243
265
|
RequestJob::Shutdown => return true,
|
@@ -276,12 +298,11 @@ impl ThreadWorker {
|
|
276
298
|
})
|
277
299
|
}
|
278
300
|
|
279
|
-
#[instrument(skip_all, fields(thread_worker=
|
301
|
+
#[instrument(skip_all, fields(thread_worker=name))]
|
280
302
|
pub fn fiber_accept_loop(
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
app: Opaque<Value>,
|
303
|
+
self: Arc<Self>,
|
304
|
+
params: Arc<ServerParams>,
|
305
|
+
name: String,
|
285
306
|
receiver: Arc<async_channel::Receiver<RequestJob>>,
|
286
307
|
scheduler_class: Opaque<Value>,
|
287
308
|
terminated: Arc<AtomicBool>,
|
@@ -290,13 +311,12 @@ impl ThreadWorker {
|
|
290
311
|
let (waker_sender, waker_receiver) = watch::channel(TerminateWakerSignal(false));
|
291
312
|
let leader: Arc<Mutex<Option<RequestJob>>> = Arc::new(Mutex::new(None));
|
292
313
|
let server_class = ruby.get_inner(&ITSI_SERVER);
|
293
|
-
let scheduler_proc =
|
294
|
-
app,
|
314
|
+
let scheduler_proc = self.build_scheduler_proc(
|
295
315
|
&leader,
|
296
316
|
&receiver,
|
297
317
|
&terminated,
|
298
318
|
&waker_sender,
|
299
|
-
|
319
|
+
params.oob_gc_responses_threshold,
|
300
320
|
);
|
301
321
|
let (scheduler, scheduler_fiber) = server_class.funcall::<_, _, (Value, Value)>(
|
302
322
|
"start_scheduler_loop",
|
@@ -359,35 +379,60 @@ impl ThreadWorker {
|
|
359
379
|
|
360
380
|
#[instrument(skip_all, fields(thread_worker=id))]
|
361
381
|
pub fn accept_loop(
|
362
|
-
|
382
|
+
self: Arc<Self>,
|
383
|
+
params: Arc<ServerParams>,
|
363
384
|
id: String,
|
364
|
-
app: Opaque<Value>,
|
365
385
|
receiver: Arc<async_channel::Receiver<RequestJob>>,
|
366
386
|
terminated: Arc<AtomicBool>,
|
367
387
|
) {
|
368
388
|
let ruby = Ruby::get().unwrap();
|
369
|
-
let server_class = ruby.get_inner(&ITSI_SERVER);
|
370
389
|
let mut idle_counter = 0;
|
390
|
+
let self_ref = self.clone();
|
371
391
|
call_without_gvl(|| loop {
|
372
392
|
if receiver.is_empty() {
|
373
|
-
if let Some(oob_gc_threshold) =
|
393
|
+
if let Some(oob_gc_threshold) = params.oob_gc_responses_threshold {
|
374
394
|
idle_counter = (idle_counter + 1) % oob_gc_threshold;
|
375
395
|
if idle_counter == 0 {
|
376
|
-
|
396
|
+
call_with_gvl(|_ruby| {
|
397
|
+
ruby.gc_start();
|
398
|
+
});
|
377
399
|
}
|
378
400
|
};
|
379
401
|
}
|
380
402
|
match receiver.recv_blocking() {
|
381
|
-
Ok(RequestJob::
|
403
|
+
Ok(RequestJob::ProcessHttpRequest(request, app_proc)) => {
|
404
|
+
self_ref.request_id.fetch_add(1, Ordering::Relaxed);
|
405
|
+
self_ref.current_request_start.store(
|
406
|
+
SystemTime::now()
|
407
|
+
.duration_since(UNIX_EPOCH)
|
408
|
+
.unwrap()
|
409
|
+
.as_secs(),
|
410
|
+
Ordering::Relaxed,
|
411
|
+
);
|
412
|
+
call_with_gvl(|_ruby| {
|
413
|
+
request.process(&ruby, app_proc).ok();
|
414
|
+
});
|
382
415
|
if terminated.load(Ordering::Relaxed) {
|
383
416
|
break;
|
384
417
|
}
|
418
|
+
}
|
419
|
+
Ok(RequestJob::ProcessGrpcRequest(request, app_proc)) => {
|
420
|
+
self_ref.request_id.fetch_add(1, Ordering::Relaxed);
|
421
|
+
self_ref.current_request_start.store(
|
422
|
+
SystemTime::now()
|
423
|
+
.duration_since(UNIX_EPOCH)
|
424
|
+
.unwrap()
|
425
|
+
.as_secs(),
|
426
|
+
Ordering::Relaxed,
|
427
|
+
);
|
385
428
|
call_with_gvl(|_ruby| {
|
386
|
-
request.process(&ruby,
|
387
|
-
})
|
429
|
+
request.process(&ruby, app_proc).ok();
|
430
|
+
});
|
431
|
+
if terminated.load(Ordering::Relaxed) {
|
432
|
+
break;
|
433
|
+
}
|
388
434
|
}
|
389
435
|
Ok(RequestJob::Shutdown) => {
|
390
|
-
debug!("Shutting down thread worker");
|
391
436
|
break;
|
392
437
|
}
|
393
438
|
Err(_) => {
|
@@ -0,0 +1,43 @@
|
|
1
|
+
use std::convert::Infallible;
|
2
|
+
|
3
|
+
use bytes::Bytes;
|
4
|
+
use http::{Request, Response};
|
5
|
+
use http_body_util::combinators::BoxBody;
|
6
|
+
use hyper::body::Incoming;
|
7
|
+
|
8
|
+
pub type HttpResponse = Response<BoxBody<Bytes, Infallible>>;
|
9
|
+
pub type HttpRequest = Request<Incoming>;
|
10
|
+
|
11
|
+
pub trait RequestExt {
|
12
|
+
fn content_type(&self) -> Option<&str>;
|
13
|
+
fn accept(&self) -> Option<&str>;
|
14
|
+
fn header(&self, header_name: &str) -> Option<&str>;
|
15
|
+
fn query_param(&self, query_name: &str) -> Option<&str>;
|
16
|
+
}
|
17
|
+
|
18
|
+
impl RequestExt for HttpRequest {
|
19
|
+
fn content_type(&self) -> Option<&str> {
|
20
|
+
self.headers()
|
21
|
+
.get("content-type")
|
22
|
+
.map(|hv| hv.to_str().unwrap_or(""))
|
23
|
+
}
|
24
|
+
|
25
|
+
fn accept(&self) -> Option<&str> {
|
26
|
+
self.headers()
|
27
|
+
.get("accept")
|
28
|
+
.map(|hv| hv.to_str().unwrap_or(""))
|
29
|
+
}
|
30
|
+
|
31
|
+
fn header(&self, header_name: &str) -> Option<&str> {
|
32
|
+
self.headers()
|
33
|
+
.get(header_name)
|
34
|
+
.map(|hv| hv.to_str().unwrap_or(""))
|
35
|
+
}
|
36
|
+
|
37
|
+
fn query_param(&self, query_name: &str) -> Option<&str> {
|
38
|
+
self.uri()
|
39
|
+
.query()
|
40
|
+
.and_then(|query| query.split('&').find(|param| param.starts_with(query_name)))
|
41
|
+
.map(|param| param.split('=').nth(1).unwrap_or(""))
|
42
|
+
}
|
43
|
+
}
|
data/ext/itsi_tracing/Cargo.toml
CHANGED