itsi-scheduler 0.1.5 → 0.1.19

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.

Potentially problematic release.


This version of itsi-scheduler might be problematic. Click here for more details.

Files changed (125) hide show
  1. checksums.yaml +4 -4
  2. data/CODE_OF_CONDUCT.md +7 -0
  3. data/Cargo.lock +90 -22
  4. data/README.md +5 -0
  5. data/_index.md +7 -0
  6. data/ext/itsi_error/Cargo.toml +1 -0
  7. data/ext/itsi_error/src/lib.rs +106 -7
  8. data/ext/itsi_error/target/debug/build/clang-sys-da71b0344e568175/out/common.rs +355 -0
  9. data/ext/itsi_error/target/debug/build/clang-sys-da71b0344e568175/out/dynamic.rs +276 -0
  10. data/ext/itsi_error/target/debug/build/clang-sys-da71b0344e568175/out/macros.rs +49 -0
  11. data/ext/itsi_error/target/debug/build/rb-sys-49f554618693db24/out/bindings-0.9.110-mri-arm64-darwin23-3.4.2.rs +8865 -0
  12. data/ext/itsi_error/target/debug/incremental/itsi_error-1mmt5sux7jb0i/s-h510z7m8v9-0bxu7yd.lock +0 -0
  13. data/ext/itsi_error/target/debug/incremental/itsi_error-2vn3jey74oiw0/s-h5113n0e7e-1v5qzs6.lock +0 -0
  14. data/ext/itsi_error/target/debug/incremental/itsi_error-37uv9dicz7awp/s-h510ykifhe-0tbnep2.lock +0 -0
  15. data/ext/itsi_error/target/debug/incremental/itsi_error-37uv9dicz7awp/s-h510yyocpj-0tz7ug7.lock +0 -0
  16. data/ext/itsi_error/target/debug/incremental/itsi_error-37uv9dicz7awp/s-h510z0xc8g-14ol18k.lock +0 -0
  17. data/ext/itsi_error/target/debug/incremental/itsi_error-3g5qf4y7d54uj/s-h5113n0e7d-1trk8on.lock +0 -0
  18. data/ext/itsi_error/target/debug/incremental/itsi_error-3lpfftm45d3e2/s-h510z7m8r3-1pxp20o.lock +0 -0
  19. data/ext/itsi_error/target/debug/incremental/itsi_error-3o4qownhl3d7n/s-h510ykifek-1uxasnk.lock +0 -0
  20. data/ext/itsi_error/target/debug/incremental/itsi_error-3o4qownhl3d7n/s-h510yyocki-11u37qm.lock +0 -0
  21. data/ext/itsi_error/target/debug/incremental/itsi_error-3o4qownhl3d7n/s-h510z0xc93-0pmy0zm.lock +0 -0
  22. data/ext/itsi_rb_helpers/Cargo.toml +1 -0
  23. data/ext/itsi_rb_helpers/src/heap_value.rs +18 -0
  24. data/ext/itsi_rb_helpers/src/lib.rs +59 -9
  25. data/ext/itsi_rb_helpers/target/debug/build/clang-sys-da71b0344e568175/out/common.rs +355 -0
  26. data/ext/itsi_rb_helpers/target/debug/build/clang-sys-da71b0344e568175/out/dynamic.rs +276 -0
  27. data/ext/itsi_rb_helpers/target/debug/build/clang-sys-da71b0344e568175/out/macros.rs +49 -0
  28. 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
  29. data/ext/itsi_rb_helpers/target/debug/incremental/itsi_rb_helpers-040pxg6yhb3g3/s-h5113n7a1b-03bwlt4.lock +0 -0
  30. data/ext/itsi_rb_helpers/target/debug/incremental/itsi_rb_helpers-131g1u4dzkt1a/s-h51113xnh3-1eik1ip.lock +0 -0
  31. data/ext/itsi_rb_helpers/target/debug/incremental/itsi_rb_helpers-131g1u4dzkt1a/s-h5111704jj-0g4rj8x.lock +0 -0
  32. data/ext/itsi_rb_helpers/target/debug/incremental/itsi_rb_helpers-1q2d3drtxrzs5/s-h5113n79yl-0bxcqc5.lock +0 -0
  33. data/ext/itsi_rb_helpers/target/debug/incremental/itsi_rb_helpers-374a9h7ovycj0/s-h51113xoox-10de2hp.lock +0 -0
  34. data/ext/itsi_rb_helpers/target/debug/incremental/itsi_rb_helpers-374a9h7ovycj0/s-h5111704w7-0vdq7gq.lock +0 -0
  35. data/ext/itsi_scheduler/src/itsi_scheduler.rs +1 -1
  36. data/ext/itsi_server/Cargo.lock +2956 -0
  37. data/ext/itsi_server/Cargo.toml +72 -28
  38. data/ext/itsi_server/src/default_responses/mod.rs +11 -0
  39. data/ext/itsi_server/src/env.rs +43 -0
  40. data/ext/itsi_server/src/lib.rs +113 -75
  41. data/ext/itsi_server/src/prelude.rs +2 -0
  42. data/ext/itsi_server/src/{body_proxy → ruby_types/itsi_body_proxy}/big_bytes.rs +10 -5
  43. data/ext/itsi_server/src/{body_proxy/itsi_body_proxy.rs → ruby_types/itsi_body_proxy/mod.rs} +29 -8
  44. data/ext/itsi_server/src/ruby_types/itsi_grpc_call.rs +344 -0
  45. data/ext/itsi_server/src/ruby_types/itsi_grpc_response_stream/mod.rs +264 -0
  46. data/ext/itsi_server/src/ruby_types/itsi_http_request.rs +345 -0
  47. data/ext/itsi_server/src/{response/itsi_response.rs → ruby_types/itsi_http_response.rs} +84 -40
  48. data/ext/itsi_server/src/ruby_types/itsi_server/file_watcher.rs +225 -0
  49. data/ext/itsi_server/src/ruby_types/itsi_server/itsi_server_config.rs +375 -0
  50. data/ext/itsi_server/src/ruby_types/itsi_server.rs +83 -0
  51. data/ext/itsi_server/src/ruby_types/mod.rs +48 -0
  52. data/ext/itsi_server/src/server/{bind.rs → binds/bind.rs} +56 -24
  53. data/ext/itsi_server/src/server/{listener.rs → binds/listener.rs} +218 -113
  54. data/ext/itsi_server/src/server/binds/mod.rs +4 -0
  55. data/ext/itsi_server/src/server/{tls → binds/tls}/locked_dir_cache.rs +55 -17
  56. data/ext/itsi_server/src/server/{tls.rs → binds/tls.rs} +109 -28
  57. data/ext/itsi_server/src/server/byte_frame.rs +32 -0
  58. data/ext/itsi_server/src/server/http_message_types.rs +97 -0
  59. data/ext/itsi_server/src/server/io_stream.rs +2 -1
  60. data/ext/itsi_server/src/server/lifecycle_event.rs +3 -0
  61. data/ext/itsi_server/src/server/middleware_stack/middleware.rs +165 -0
  62. data/ext/itsi_server/src/server/middleware_stack/middlewares/allow_list.rs +56 -0
  63. data/ext/itsi_server/src/server/middleware_stack/middlewares/auth_api_key.rs +87 -0
  64. data/ext/itsi_server/src/server/middleware_stack/middlewares/auth_basic.rs +86 -0
  65. data/ext/itsi_server/src/server/middleware_stack/middlewares/auth_jwt.rs +285 -0
  66. data/ext/itsi_server/src/server/middleware_stack/middlewares/cache_control.rs +142 -0
  67. data/ext/itsi_server/src/server/middleware_stack/middlewares/compression.rs +289 -0
  68. data/ext/itsi_server/src/server/middleware_stack/middlewares/cors.rs +292 -0
  69. data/ext/itsi_server/src/server/middleware_stack/middlewares/deny_list.rs +55 -0
  70. data/ext/itsi_server/src/server/middleware_stack/middlewares/error_response/default_responses.rs +190 -0
  71. data/ext/itsi_server/src/server/middleware_stack/middlewares/error_response.rs +157 -0
  72. data/ext/itsi_server/src/server/middleware_stack/middlewares/etag.rs +195 -0
  73. data/ext/itsi_server/src/server/middleware_stack/middlewares/header_interpretation.rs +82 -0
  74. data/ext/itsi_server/src/server/middleware_stack/middlewares/intrusion_protection.rs +201 -0
  75. data/ext/itsi_server/src/server/middleware_stack/middlewares/log_requests.rs +82 -0
  76. data/ext/itsi_server/src/server/middleware_stack/middlewares/max_body.rs +47 -0
  77. data/ext/itsi_server/src/server/middleware_stack/middlewares/mod.rs +87 -0
  78. data/ext/itsi_server/src/server/middleware_stack/middlewares/proxy.rs +414 -0
  79. data/ext/itsi_server/src/server/middleware_stack/middlewares/rate_limit.rs +131 -0
  80. data/ext/itsi_server/src/server/middleware_stack/middlewares/redirect.rs +76 -0
  81. data/ext/itsi_server/src/server/middleware_stack/middlewares/request_headers.rs +44 -0
  82. data/ext/itsi_server/src/server/middleware_stack/middlewares/response_headers.rs +36 -0
  83. data/ext/itsi_server/src/server/middleware_stack/middlewares/ruby_app.rs +126 -0
  84. data/ext/itsi_server/src/server/middleware_stack/middlewares/static_assets.rs +180 -0
  85. data/ext/itsi_server/src/server/middleware_stack/middlewares/static_response.rs +55 -0
  86. data/ext/itsi_server/src/server/middleware_stack/middlewares/string_rewrite.rs +163 -0
  87. data/ext/itsi_server/src/server/middleware_stack/middlewares/token_source.rs +12 -0
  88. data/ext/itsi_server/src/server/middleware_stack/mod.rs +347 -0
  89. data/ext/itsi_server/src/server/mod.rs +6 -5
  90. data/ext/itsi_server/src/server/process_worker.rs +65 -14
  91. data/ext/itsi_server/src/server/request_job.rs +11 -0
  92. data/ext/itsi_server/src/server/serve_strategy/cluster_mode.rs +137 -49
  93. data/ext/itsi_server/src/server/serve_strategy/mod.rs +9 -6
  94. data/ext/itsi_server/src/server/serve_strategy/single_mode.rs +338 -164
  95. data/ext/itsi_server/src/server/signal.rs +32 -26
  96. data/ext/itsi_server/src/server/size_limited_incoming.rs +101 -0
  97. data/ext/itsi_server/src/server/thread_worker.rs +214 -107
  98. data/ext/itsi_server/src/services/cache_store.rs +74 -0
  99. data/ext/itsi_server/src/services/itsi_http_service.rs +239 -0
  100. data/ext/itsi_server/src/services/mime_types.rs +1416 -0
  101. data/ext/itsi_server/src/services/mod.rs +6 -0
  102. data/ext/itsi_server/src/services/password_hasher.rs +83 -0
  103. data/ext/itsi_server/src/services/rate_limiter.rs +569 -0
  104. data/ext/itsi_server/src/services/static_file_server.rs +1324 -0
  105. data/ext/itsi_tracing/Cargo.toml +1 -0
  106. data/ext/itsi_tracing/src/lib.rs +312 -34
  107. data/ext/itsi_tracing/target/debug/incremental/itsi_tracing-0994n8rpvvt9m/s-h510hfz1f6-1kbycmq.lock +0 -0
  108. data/ext/itsi_tracing/target/debug/incremental/itsi_tracing-0bob7bf4yq34i/s-h5113125h5-0lh4rag.lock +0 -0
  109. data/ext/itsi_tracing/target/debug/incremental/itsi_tracing-2fcodulrxbbxo/s-h510h2infk-0hp5kjw.lock +0 -0
  110. data/ext/itsi_tracing/target/debug/incremental/itsi_tracing-2iak63r1woi1l/s-h510h2in4q-0kxfzw1.lock +0 -0
  111. data/ext/itsi_tracing/target/debug/incremental/itsi_tracing-2kk4qj9gn5dg2/s-h5113124kv-0enwon2.lock +0 -0
  112. data/ext/itsi_tracing/target/debug/incremental/itsi_tracing-2mwo0yas7dtw4/s-h510hfz1ha-1udgpei.lock +0 -0
  113. data/lib/itsi/scheduler/version.rb +1 -1
  114. data/lib/itsi/scheduler.rb +2 -2
  115. metadata +93 -21
  116. data/ext/itsi_error/src/from.rs +0 -71
  117. data/ext/itsi_server/extconf.rb +0 -6
  118. data/ext/itsi_server/src/body_proxy/mod.rs +0 -2
  119. data/ext/itsi_server/src/request/itsi_request.rs +0 -277
  120. data/ext/itsi_server/src/request/mod.rs +0 -1
  121. data/ext/itsi_server/src/response/mod.rs +0 -1
  122. data/ext/itsi_server/src/server/itsi_ca/itsi_ca.crt +0 -13
  123. data/ext/itsi_server/src/server/itsi_ca/itsi_ca.key +0 -5
  124. data/ext/itsi_server/src/server/itsi_server.rs +0 -244
  125. /data/ext/itsi_server/src/server/{bind_protocol.rs → binds/bind_protocol.rs} +0 -0
@@ -1,277 +0,0 @@
1
- use crate::{
2
- body_proxy::{
3
- big_bytes::BigBytes,
4
- itsi_body_proxy::{ItsiBody, ItsiBodyProxy},
5
- },
6
- response::itsi_response::ItsiResponse,
7
- server::{
8
- itsi_server::{RequestJob, Server},
9
- listener::{SockAddr, TokioListener},
10
- serve_strategy::single_mode::RunningPhase,
11
- },
12
- };
13
- use bytes::Bytes;
14
- use derive_more::Debug;
15
- use futures::StreamExt;
16
- use http::{request::Parts, Response, StatusCode};
17
- use http_body_util::{combinators::BoxBody, BodyExt, Empty};
18
- use hyper::{body::Incoming, Request};
19
- use itsi_error::from::CLIENT_CONNECTION_CLOSED;
20
- use itsi_tracing::{debug, error};
21
- use magnus::{
22
- error::{ErrorType, Result as MagnusResult},
23
- Error,
24
- };
25
- use magnus::{
26
- value::{LazyId, Opaque, ReprValue},
27
- RClass, Ruby, Value,
28
- };
29
- use std::{convert::Infallible, fmt, io::Write, sync::Arc, time::Instant};
30
- use tokio::sync::{
31
- mpsc::{self},
32
- watch,
33
- };
34
- static ID_CALL: LazyId = LazyId::new("call");
35
- static ID_MESSAGE: LazyId = LazyId::new("message");
36
- static ID_BACKTRACE: LazyId = LazyId::new("backtrace");
37
-
38
- #[derive(Debug)]
39
- #[magnus::wrap(class = "Itsi::Request", free_immediately, size)]
40
- pub struct ItsiRequest {
41
- pub parts: Parts,
42
- #[debug(skip)]
43
- pub body: ItsiBody,
44
- pub remote_addr: String,
45
- pub version: String,
46
- #[debug(skip)]
47
- pub(crate) listener: Arc<TokioListener>,
48
- #[debug(skip)]
49
- pub server: Arc<Server>,
50
- pub response: ItsiResponse,
51
- pub start: Instant,
52
- }
53
-
54
- impl fmt::Display for ItsiRequest {
55
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
56
- write!(
57
- f,
58
- "{} {} {}",
59
- self.version().unwrap(),
60
- self.method().unwrap(),
61
- self.path().unwrap()
62
- )
63
- }
64
- }
65
-
66
- impl ItsiRequest {
67
- pub fn is_connection_closed_err(ruby: &Ruby, err: &Error) -> bool {
68
- match err.error_type() {
69
- ErrorType::Jump(_) => false,
70
- ErrorType::Error(_, _) => false,
71
- ErrorType::Exception(exception) => {
72
- exception.is_kind_of(ruby.exception_eof_error())
73
- && err
74
- .value()
75
- .map(|v| {
76
- v.funcall::<_, _, String>(*ID_MESSAGE, ())
77
- .unwrap_or("".to_string())
78
- .eq(CLIENT_CONNECTION_CLOSED)
79
- })
80
- .unwrap_or(false)
81
- }
82
- }
83
- }
84
-
85
- pub fn process(
86
- self,
87
- ruby: &Ruby,
88
- server: RClass,
89
- app: Opaque<Value>,
90
- ) -> magnus::error::Result<()> {
91
- let req = format!("{}", self);
92
- let response = self.response.clone();
93
- let start = self.start;
94
- debug!("{} Started", req);
95
- let result = server.funcall::<_, _, Value>(*ID_CALL, (app, self));
96
- if let Err(err) = result {
97
- Self::internal_error(ruby, response, err);
98
- }
99
- debug!("{} Finished in {:?}", req, start.elapsed());
100
-
101
- Ok(())
102
- }
103
-
104
- pub fn internal_error(ruby: &Ruby, response: ItsiResponse, err: Error) {
105
- if Self::is_connection_closed_err(ruby, &err) {
106
- debug!("Connection closed by client");
107
- response.close();
108
- } else if let Some(rb_err) = err.value() {
109
- let backtrace = rb_err
110
- .funcall::<_, _, Vec<String>>(*ID_BACKTRACE, ())
111
- .unwrap_or_default();
112
-
113
- error!("Error occurred in Handler: {:?}", rb_err);
114
- for line in backtrace {
115
- error!("{}", line);
116
- }
117
- response.internal_server_error(err.to_string());
118
- } else {
119
- response.internal_server_error(err.to_string());
120
- }
121
- }
122
-
123
- pub fn error(self, message: String) {
124
- self.response.internal_server_error(message);
125
- }
126
-
127
- pub(crate) async fn process_request(
128
- hyper_request: Request<Incoming>,
129
- sender: async_channel::Sender<RequestJob>,
130
- server: Arc<Server>,
131
- listener: Arc<TokioListener>,
132
- addr: SockAddr,
133
- shutdown_rx: watch::Receiver<RunningPhase>,
134
- ) -> itsi_error::Result<Response<BoxBody<Bytes, Infallible>>> {
135
- let (request, mut receiver) = ItsiRequest::new(hyper_request, addr, server, listener).await;
136
-
137
- let response = request.response.clone();
138
- match sender.send(RequestJob::ProcessRequest(request)).await {
139
- Err(err) => {
140
- error!("Error occurred: {}", err);
141
- let mut response = Response::new(BoxBody::new(Empty::new()));
142
- *response.status_mut() = StatusCode::BAD_REQUEST;
143
- Ok(response)
144
- }
145
- _ => match receiver.recv().await {
146
- Some(first_frame) => Ok(response.build(first_frame, receiver, shutdown_rx).await),
147
- None => Ok(response.build(None, receiver, shutdown_rx).await),
148
- },
149
- }
150
- }
151
-
152
- pub(crate) async fn new(
153
- request: Request<Incoming>,
154
- sock_addr: SockAddr,
155
- server: Arc<Server>,
156
- listener: Arc<TokioListener>,
157
- ) -> (ItsiRequest, mpsc::Receiver<Option<Bytes>>) {
158
- let (parts, body) = request.into_parts();
159
- let body = if server.stream_body.is_some_and(|f| f) {
160
- ItsiBody::Stream(ItsiBodyProxy::new(body))
161
- } else {
162
- let mut body_bytes = BigBytes::new();
163
- let mut stream = body.into_data_stream();
164
- while let Some(chunk) = stream.next().await {
165
- let byte_array = chunk.unwrap().to_vec();
166
- body_bytes.write_all(&byte_array).unwrap();
167
- }
168
- ItsiBody::Buffered(body_bytes)
169
- };
170
- let response_channel = mpsc::channel::<Option<Bytes>>(100);
171
- (
172
- Self {
173
- remote_addr: sock_addr.to_string(),
174
- body,
175
- server,
176
- listener,
177
- version: format!("{:?}", &parts.version),
178
- response: ItsiResponse::new(parts.clone(), response_channel.0),
179
- start: Instant::now(),
180
- parts,
181
- },
182
- response_channel.1,
183
- )
184
- }
185
-
186
- pub(crate) fn path(&self) -> MagnusResult<&str> {
187
- Ok(self
188
- .parts
189
- .uri
190
- .path()
191
- .strip_prefix(&self.server.script_name)
192
- .unwrap_or(self.parts.uri.path()))
193
- }
194
-
195
- pub(crate) fn script_name(&self) -> MagnusResult<&str> {
196
- Ok(&self.server.script_name)
197
- }
198
-
199
- pub(crate) fn query_string(&self) -> MagnusResult<&str> {
200
- Ok(self.parts.uri.query().unwrap_or(""))
201
- }
202
-
203
- pub(crate) fn method(&self) -> MagnusResult<&str> {
204
- Ok(self.parts.method.as_str())
205
- }
206
-
207
- pub(crate) fn version(&self) -> MagnusResult<&str> {
208
- Ok(&self.version)
209
- }
210
-
211
- pub(crate) fn rack_protocol(&self) -> MagnusResult<Vec<&str>> {
212
- Ok(self
213
- .parts
214
- .headers
215
- .get("upgrade")
216
- .or_else(|| self.parts.headers.get("protocol"))
217
- .map(|value| {
218
- value
219
- .to_str()
220
- .unwrap_or("")
221
- .split(',')
222
- .map(|s| s.trim())
223
- .collect::<Vec<&str>>()
224
- })
225
- .unwrap_or_else(|| vec!["http"]))
226
- }
227
-
228
- pub(crate) fn host(&self) -> MagnusResult<String> {
229
- Ok(self
230
- .parts
231
- .uri
232
- .host()
233
- .map(|host| host.to_string())
234
- .unwrap_or_else(|| self.listener.host()))
235
- }
236
-
237
- pub(crate) fn scheme(&self) -> MagnusResult<String> {
238
- Ok(self
239
- .parts
240
- .uri
241
- .scheme()
242
- .map(|scheme| scheme.to_string())
243
- .unwrap_or_else(|| self.listener.scheme()))
244
- }
245
-
246
- pub(crate) fn headers(&self) -> MagnusResult<Vec<(String, &str)>> {
247
- Ok(self
248
- .parts
249
- .headers
250
- .iter()
251
- .map(|(hn, hv)| {
252
- let key = match hn.as_str() {
253
- "content-length" => "CONTENT_LENGTH".to_string(),
254
- "content-type" => "CONTENT_TYPE".to_string(),
255
- _ => format!("HTTP_{}", hn.as_str().to_uppercase().replace("-", "_")),
256
- };
257
- (key, hv.to_str().unwrap_or(""))
258
- })
259
- .collect())
260
- }
261
-
262
- pub(crate) fn remote_addr(&self) -> MagnusResult<&str> {
263
- Ok(&self.remote_addr)
264
- }
265
-
266
- pub(crate) fn port(&self) -> MagnusResult<u16> {
267
- Ok(self.parts.uri.port_u16().unwrap_or(self.listener.port()))
268
- }
269
-
270
- pub(crate) fn body(&self) -> MagnusResult<Value> {
271
- Ok(self.body.into_value())
272
- }
273
-
274
- pub(crate) fn response(&self) -> MagnusResult<ItsiResponse> {
275
- Ok(self.response.clone())
276
- }
277
- }
@@ -1 +0,0 @@
1
- pub mod itsi_request;
@@ -1 +0,0 @@
1
- pub mod itsi_response;
@@ -1,13 +0,0 @@
1
- -----BEGIN CERTIFICATE-----
2
- MIIB9TCCAZugAwIBAgIUMpQtAScU2Ow9c1Xy/0b/kS/BuwcwCgYIKoZIzj0EAwIw
3
- UDELMAkGA1UEBhMCVVMxDTALBgNVBAgMBEl0c2kxDTALBgNVBAcMBEl0c2kxEDAO
4
- BgNVBAoMB0l0c2kgQ0ExETAPBgNVBAMMCGl0c2kuZnlpMB4XDTI1MDMwMzIwMjg1
5
- N1oXDTM1MDMwMTIwMjg1N1owUDELMAkGA1UEBhMCVVMxDTALBgNVBAgMBEl0c2kx
6
- DTALBgNVBAcMBEl0c2kxEDAOBgNVBAoMB0l0c2kgQ0ExETAPBgNVBAMMCGl0c2ku
7
- ZnlpMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEqGdC9Vi1r7ARvqSkPXkAgiV5
8
- gn2MMTeEafagrWT7G1onSh/G+Qstxl61kfFNLOTiy6NSgAtKG+gfveCTo0Pcz6NT
9
- MFEwHQYDVR0OBBYEFN7zzDodmiK2VAzLDydDvb6Er+U+MB8GA1UdIwQYMBaAFN7z
10
- zDodmiK2VAzLDydDvb6Er+U+MA8GA1UdEwEB/wQFMAMBAf8wCgYIKoZIzj0EAwID
11
- SAAwRQIhAP8q3PiwqTwCbRvYvvetxH39mAce1mfQMosb33ns228VAiBXdb+p9s0o
12
- 5ug5g9/MTvrIPI7GgolXCWZunkouy0LSrw==
13
- -----END CERTIFICATE-----
@@ -1,5 +0,0 @@
1
- -----BEGIN PRIVATE KEY-----
2
- MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgC7WOxDmO7pBvDvYn
3
- YI8+z2/2c0ChxBsuJkQq/dXi1RyhRANCAASoZ0L1WLWvsBG+pKQ9eQCCJXmCfYwx
4
- N4Rp9qCtZPsbWidKH8b5Cy3GXrWR8U0s5OLLo1KAC0ob6B+94JOjQ9zP
5
- -----END PRIVATE KEY-----
@@ -1,244 +0,0 @@
1
- use super::{
2
- bind::Bind,
3
- listener::Listener,
4
- serve_strategy::{cluster_mode::ClusterMode, single_mode::SingleMode},
5
- signal::{clear_signal_handlers, reset_signal_handlers, SIGNAL_HANDLER_CHANNEL},
6
- };
7
- use crate::{request::itsi_request::ItsiRequest, server::serve_strategy::ServeStrategy};
8
- use derive_more::Debug;
9
- use itsi_rb_helpers::call_without_gvl;
10
- use itsi_tracing::error;
11
- use magnus::{
12
- block::Proc,
13
- error::Result,
14
- scan_args::{get_kwargs, scan_args, Args, KwArgs},
15
- value::{InnerValue, Opaque, ReprValue},
16
- RHash, Ruby, Symbol, Value,
17
- };
18
- use parking_lot::Mutex;
19
- use std::{cmp::max, ops::Deref, sync::Arc};
20
- use tracing::{info, instrument};
21
-
22
- static DEFAULT_BIND: &str = "localhost:3000";
23
-
24
- #[magnus::wrap(class = "Itsi::Server", free_immediately, size)]
25
- #[derive(Clone)]
26
- pub struct Server {
27
- pub config: Arc<ServerConfig>,
28
- }
29
-
30
- impl Deref for Server {
31
- type Target = ServerConfig;
32
-
33
- fn deref(&self) -> &Self::Target {
34
- &self.config
35
- }
36
- }
37
- type AfterFork = Mutex<Arc<Option<Box<dyn Fn() + Send + Sync>>>>;
38
-
39
- #[derive(Debug)]
40
- pub struct ServerConfig {
41
- #[debug(skip)]
42
- pub app: Opaque<Value>,
43
- #[allow(unused)]
44
- pub workers: u8,
45
- #[allow(unused)]
46
- pub threads: u8,
47
- #[allow(unused)]
48
- pub shutdown_timeout: f64,
49
- pub script_name: String,
50
- pub(crate) binds: Mutex<Vec<Bind>>,
51
- #[debug(skip)]
52
- pub before_fork: Mutex<Option<Box<dyn FnOnce() + Send + Sync>>>,
53
- #[debug(skip)]
54
- pub after_fork: AfterFork,
55
- pub scheduler_class: Option<String>,
56
- pub stream_body: Option<bool>,
57
- pub worker_memory_limit: Option<u64>,
58
- }
59
-
60
- #[derive(Debug)]
61
- pub enum RequestJob {
62
- ProcessRequest(ItsiRequest),
63
- Shutdown,
64
- }
65
-
66
- impl Server {
67
- #[instrument(
68
- name = "Itsi",
69
- parent=None,
70
- skip(args),
71
- fields(workers = 1, threads = 1, shutdown_timeout = 5)
72
- )]
73
- pub fn new(args: &[Value]) -> Result<Self> {
74
- let scan_args: Args<(), (), (), (), RHash, ()> = scan_args(args)?;
75
-
76
- type ArgSet1 = (
77
- Option<u8>,
78
- Option<u8>,
79
- Option<f64>,
80
- Option<String>,
81
- Option<Vec<String>>,
82
- Option<Proc>,
83
- Option<Proc>,
84
- Option<String>,
85
- Option<bool>,
86
- );
87
-
88
- type ArgSet2 = (Option<u64>,);
89
-
90
- let args1: KwArgs<(Value,), ArgSet1, ()> = get_kwargs(
91
- scan_args
92
- .keywords
93
- .funcall::<_, _, RHash>(
94
- "slice",
95
- (
96
- Symbol::new("app"),
97
- Symbol::new("workers"),
98
- Symbol::new("threads"),
99
- Symbol::new("shutdown_timeout"),
100
- Symbol::new("script_name"),
101
- Symbol::new("binds"),
102
- Symbol::new("before_fork"),
103
- Symbol::new("after_fork"),
104
- Symbol::new("scheduler_class"),
105
- Symbol::new("stream_body"),
106
- ),
107
- )
108
- .unwrap(),
109
- &["app"],
110
- &[
111
- "workers",
112
- "threads",
113
- "shutdown_timeout",
114
- "script_name",
115
- "binds",
116
- "before_fork",
117
- "after_fork",
118
- "scheduler_class",
119
- "stream_body",
120
- ],
121
- )?;
122
-
123
- let args2: KwArgs<(), ArgSet2, ()> = get_kwargs(
124
- scan_args
125
- .keywords
126
- .funcall::<_, _, RHash>("slice", (Symbol::new("worker_memory_limit"),))
127
- .unwrap(),
128
- &[],
129
- &["worker_memory_limit"],
130
- )?;
131
-
132
- let config = ServerConfig {
133
- app: Opaque::from(args1.required.0),
134
- workers: max(args1.optional.0.unwrap_or(1), 1),
135
- threads: max(args1.optional.1.unwrap_or(1), 1),
136
- shutdown_timeout: args1.optional.2.unwrap_or(5.0),
137
- script_name: args1.optional.3.unwrap_or("".to_string()),
138
- binds: Mutex::new(
139
- args1
140
- .optional
141
- .4
142
- .unwrap_or_else(|| vec![DEFAULT_BIND.to_string()])
143
- .into_iter()
144
- .map(|s| s.parse())
145
- .collect::<itsi_error::Result<Vec<Bind>>>()?,
146
- ),
147
- before_fork: Mutex::new(args1.optional.5.map(|p| {
148
- let opaque_proc = Opaque::from(p);
149
- Box::new(move || {
150
- opaque_proc
151
- .get_inner_with(&Ruby::get().unwrap())
152
- .call::<_, Value>(())
153
- .unwrap();
154
- }) as Box<dyn FnOnce() + Send + Sync>
155
- })),
156
- after_fork: Mutex::new(Arc::new(args1.optional.6.map(|p| {
157
- let opaque_proc = Opaque::from(p);
158
- Box::new(move || {
159
- opaque_proc
160
- .get_inner_with(&Ruby::get().unwrap())
161
- .call::<_, Value>(())
162
- .unwrap();
163
- }) as Box<dyn Fn() + Send + Sync>
164
- }))),
165
- scheduler_class: args1.optional.7.clone(),
166
- stream_body: args1.optional.8,
167
- worker_memory_limit: args2.optional.0,
168
- };
169
-
170
- if let Some(scheduler_class) = args1.optional.7 {
171
- info!(scheduler_class, fiber_scheduler = true);
172
- } else {
173
- info!(fiber_scheduler = false);
174
- }
175
-
176
- Ok(Server {
177
- config: Arc::new(config),
178
- })
179
- }
180
-
181
- #[instrument(name = "Bind", skip_all, fields(binds=format!("{:?}", self.config.binds.lock())))]
182
- pub(crate) fn listeners(&self) -> Result<Arc<Vec<Arc<Listener>>>> {
183
- let listeners = self
184
- .config
185
- .binds
186
- .lock()
187
- .iter()
188
- .cloned()
189
- .map(Listener::try_from)
190
- .collect::<std::result::Result<Vec<Listener>, _>>()?
191
- .into_iter()
192
- .map(Arc::new)
193
- .collect::<Vec<_>>();
194
- info!("Bound {:?} listeners", listeners.len());
195
- Ok(Arc::new(listeners))
196
- }
197
-
198
- pub(crate) fn build_strategy(
199
- self,
200
- listeners: Arc<Vec<Arc<Listener>>>,
201
- ) -> Result<ServeStrategy> {
202
- let server = Arc::new(self);
203
-
204
- let strategy = if server.config.workers == 1 {
205
- ServeStrategy::Single(Arc::new(SingleMode::new(
206
- server,
207
- listeners,
208
- SIGNAL_HANDLER_CHANNEL.0.clone(),
209
- )?))
210
- } else {
211
- ServeStrategy::Cluster(Arc::new(ClusterMode::new(
212
- server,
213
- listeners,
214
- SIGNAL_HANDLER_CHANNEL.0.clone(),
215
- )))
216
- };
217
- Ok(strategy)
218
- }
219
-
220
- pub fn start(&self) -> Result<()> {
221
- reset_signal_handlers();
222
- let rself = self.clone();
223
- let listeners = self.listeners()?;
224
- let listeners_clone = listeners.clone();
225
- call_without_gvl(move || -> Result<()> {
226
- let strategy = rself.build_strategy(listeners_clone)?;
227
- if let Err(e) = strategy.run() {
228
- error!("Error running server: {}", e);
229
- strategy.stop()?;
230
- }
231
- drop(strategy);
232
- Ok(())
233
- })?;
234
- if let Ok(listeners) = Arc::try_unwrap(listeners) {
235
- listeners.into_iter().for_each(|listener| {
236
- if let Ok(listener) = Arc::try_unwrap(listener) {
237
- listener.unbind()
238
- };
239
- });
240
- }
241
- clear_signal_handlers();
242
- Ok(())
243
- }
244
- }