itsi-server 0.1.1 → 0.1.13

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-server might be problematic. Click here for more details.

Files changed (143) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +5 -0
  3. data/CODE_OF_CONDUCT.md +7 -0
  4. data/Cargo.lock +4417 -0
  5. data/Cargo.toml +7 -0
  6. data/README.md +4 -0
  7. data/Rakefile +8 -1
  8. data/_index.md +6 -0
  9. data/exe/itsi +94 -45
  10. data/ext/itsi_error/Cargo.toml +2 -0
  11. data/ext/itsi_error/src/from.rs +68 -0
  12. data/ext/itsi_error/src/lib.rs +18 -34
  13. data/ext/itsi_error/target/debug/build/clang-sys-da71b0344e568175/out/common.rs +355 -0
  14. data/ext/itsi_error/target/debug/build/clang-sys-da71b0344e568175/out/dynamic.rs +276 -0
  15. data/ext/itsi_error/target/debug/build/clang-sys-da71b0344e568175/out/macros.rs +49 -0
  16. data/ext/itsi_error/target/debug/build/rb-sys-49f554618693db24/out/bindings-0.9.110-mri-arm64-darwin23-3.4.2.rs +8865 -0
  17. data/ext/itsi_error/target/debug/incremental/itsi_error-1mmt5sux7jb0i/s-h510z7m8v9-0bxu7yd.lock +0 -0
  18. data/ext/itsi_error/target/debug/incremental/itsi_error-2vn3jey74oiw0/s-h5113n0e7e-1v5qzs6.lock +0 -0
  19. data/ext/itsi_error/target/debug/incremental/itsi_error-37uv9dicz7awp/s-h510ykifhe-0tbnep2.lock +0 -0
  20. data/ext/itsi_error/target/debug/incremental/itsi_error-37uv9dicz7awp/s-h510yyocpj-0tz7ug7.lock +0 -0
  21. data/ext/itsi_error/target/debug/incremental/itsi_error-37uv9dicz7awp/s-h510z0xc8g-14ol18k.lock +0 -0
  22. data/ext/itsi_error/target/debug/incremental/itsi_error-3g5qf4y7d54uj/s-h5113n0e7d-1trk8on.lock +0 -0
  23. data/ext/itsi_error/target/debug/incremental/itsi_error-3lpfftm45d3e2/s-h510z7m8r3-1pxp20o.lock +0 -0
  24. data/ext/itsi_error/target/debug/incremental/itsi_error-3o4qownhl3d7n/s-h510ykifek-1uxasnk.lock +0 -0
  25. data/ext/itsi_error/target/debug/incremental/itsi_error-3o4qownhl3d7n/s-h510yyocki-11u37qm.lock +0 -0
  26. data/ext/itsi_error/target/debug/incremental/itsi_error-3o4qownhl3d7n/s-h510z0xc93-0pmy0zm.lock +0 -0
  27. data/ext/itsi_instrument_entry/Cargo.toml +15 -0
  28. data/ext/itsi_instrument_entry/src/lib.rs +31 -0
  29. data/ext/itsi_rb_helpers/Cargo.toml +3 -0
  30. data/ext/itsi_rb_helpers/src/heap_value.rs +139 -0
  31. data/ext/itsi_rb_helpers/src/lib.rs +140 -10
  32. data/ext/itsi_rb_helpers/target/debug/build/clang-sys-da71b0344e568175/out/common.rs +355 -0
  33. data/ext/itsi_rb_helpers/target/debug/build/clang-sys-da71b0344e568175/out/dynamic.rs +276 -0
  34. data/ext/itsi_rb_helpers/target/debug/build/clang-sys-da71b0344e568175/out/macros.rs +49 -0
  35. 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
  36. data/ext/itsi_rb_helpers/target/debug/incremental/itsi_rb_helpers-040pxg6yhb3g3/s-h5113n7a1b-03bwlt4.lock +0 -0
  37. data/ext/itsi_rb_helpers/target/debug/incremental/itsi_rb_helpers-131g1u4dzkt1a/s-h51113xnh3-1eik1ip.lock +0 -0
  38. data/ext/itsi_rb_helpers/target/debug/incremental/itsi_rb_helpers-131g1u4dzkt1a/s-h5111704jj-0g4rj8x.lock +0 -0
  39. data/ext/itsi_rb_helpers/target/debug/incremental/itsi_rb_helpers-1q2d3drtxrzs5/s-h5113n79yl-0bxcqc5.lock +0 -0
  40. data/ext/itsi_rb_helpers/target/debug/incremental/itsi_rb_helpers-374a9h7ovycj0/s-h51113xoox-10de2hp.lock +0 -0
  41. data/ext/itsi_rb_helpers/target/debug/incremental/itsi_rb_helpers-374a9h7ovycj0/s-h5111704w7-0vdq7gq.lock +0 -0
  42. data/ext/itsi_scheduler/Cargo.toml +24 -0
  43. data/ext/itsi_scheduler/src/itsi_scheduler/io_helpers.rs +56 -0
  44. data/ext/itsi_scheduler/src/itsi_scheduler/io_waiter.rs +44 -0
  45. data/ext/itsi_scheduler/src/itsi_scheduler/timer.rs +44 -0
  46. data/ext/itsi_scheduler/src/itsi_scheduler.rs +308 -0
  47. data/ext/itsi_scheduler/src/lib.rs +38 -0
  48. data/ext/itsi_server/Cargo.lock +2956 -0
  49. data/ext/itsi_server/Cargo.toml +73 -13
  50. data/ext/itsi_server/extconf.rb +1 -1
  51. data/ext/itsi_server/src/env.rs +43 -0
  52. data/ext/itsi_server/src/lib.rs +100 -40
  53. data/ext/itsi_server/src/ruby_types/itsi_body_proxy/big_bytes.rs +109 -0
  54. data/ext/itsi_server/src/ruby_types/itsi_body_proxy/mod.rs +141 -0
  55. data/ext/itsi_server/src/ruby_types/itsi_grpc_request.rs +147 -0
  56. data/ext/itsi_server/src/ruby_types/itsi_grpc_response.rs +19 -0
  57. data/ext/itsi_server/src/ruby_types/itsi_grpc_stream/mod.rs +216 -0
  58. data/ext/itsi_server/src/ruby_types/itsi_http_request.rs +282 -0
  59. data/ext/itsi_server/src/ruby_types/itsi_http_response.rs +388 -0
  60. data/ext/itsi_server/src/ruby_types/itsi_server/file_watcher.rs +225 -0
  61. data/ext/itsi_server/src/ruby_types/itsi_server/itsi_server_config.rs +355 -0
  62. data/ext/itsi_server/src/ruby_types/itsi_server.rs +82 -0
  63. data/ext/itsi_server/src/ruby_types/mod.rs +55 -0
  64. data/ext/itsi_server/src/server/bind.rs +75 -31
  65. data/ext/itsi_server/src/server/bind_protocol.rs +37 -0
  66. data/ext/itsi_server/src/server/byte_frame.rs +32 -0
  67. data/ext/itsi_server/src/server/cache_store.rs +74 -0
  68. data/ext/itsi_server/src/server/io_stream.rs +104 -0
  69. data/ext/itsi_server/src/server/itsi_service.rs +172 -0
  70. data/ext/itsi_server/src/server/lifecycle_event.rs +12 -0
  71. data/ext/itsi_server/src/server/listener.rs +332 -132
  72. data/ext/itsi_server/src/server/middleware_stack/middleware.rs +153 -0
  73. data/ext/itsi_server/src/server/middleware_stack/middlewares/allow_list.rs +47 -0
  74. data/ext/itsi_server/src/server/middleware_stack/middlewares/auth_api_key.rs +58 -0
  75. data/ext/itsi_server/src/server/middleware_stack/middlewares/auth_basic.rs +82 -0
  76. data/ext/itsi_server/src/server/middleware_stack/middlewares/auth_jwt.rs +321 -0
  77. data/ext/itsi_server/src/server/middleware_stack/middlewares/cache_control.rs +139 -0
  78. data/ext/itsi_server/src/server/middleware_stack/middlewares/compression.rs +300 -0
  79. data/ext/itsi_server/src/server/middleware_stack/middlewares/cors.rs +287 -0
  80. data/ext/itsi_server/src/server/middleware_stack/middlewares/deny_list.rs +48 -0
  81. data/ext/itsi_server/src/server/middleware_stack/middlewares/error_response.rs +127 -0
  82. data/ext/itsi_server/src/server/middleware_stack/middlewares/etag.rs +191 -0
  83. data/ext/itsi_server/src/server/middleware_stack/middlewares/grpc_service.rs +72 -0
  84. data/ext/itsi_server/src/server/middleware_stack/middlewares/header_interpretation.rs +85 -0
  85. data/ext/itsi_server/src/server/middleware_stack/middlewares/intrusion_protection.rs +195 -0
  86. data/ext/itsi_server/src/server/middleware_stack/middlewares/log_requests.rs +82 -0
  87. data/ext/itsi_server/src/server/middleware_stack/middlewares/mod.rs +82 -0
  88. data/ext/itsi_server/src/server/middleware_stack/middlewares/proxy.rs +216 -0
  89. data/ext/itsi_server/src/server/middleware_stack/middlewares/rate_limit.rs +124 -0
  90. data/ext/itsi_server/src/server/middleware_stack/middlewares/redirect.rs +76 -0
  91. data/ext/itsi_server/src/server/middleware_stack/middlewares/request_headers.rs +43 -0
  92. data/ext/itsi_server/src/server/middleware_stack/middlewares/response_headers.rs +34 -0
  93. data/ext/itsi_server/src/server/middleware_stack/middlewares/ruby_app.rs +93 -0
  94. data/ext/itsi_server/src/server/middleware_stack/middlewares/static_assets.rs +162 -0
  95. data/ext/itsi_server/src/server/middleware_stack/middlewares/string_rewrite.rs +158 -0
  96. data/ext/itsi_server/src/server/middleware_stack/middlewares/token_source.rs +12 -0
  97. data/ext/itsi_server/src/server/middleware_stack/mod.rs +315 -0
  98. data/ext/itsi_server/src/server/mod.rs +15 -2
  99. data/ext/itsi_server/src/server/process_worker.rs +229 -0
  100. data/ext/itsi_server/src/server/rate_limiter.rs +565 -0
  101. data/ext/itsi_server/src/server/request_job.rs +11 -0
  102. data/ext/itsi_server/src/server/serve_strategy/cluster_mode.rs +337 -0
  103. data/ext/itsi_server/src/server/serve_strategy/mod.rs +30 -0
  104. data/ext/itsi_server/src/server/serve_strategy/single_mode.rs +421 -0
  105. data/ext/itsi_server/src/server/signal.rs +93 -0
  106. data/ext/itsi_server/src/server/static_file_server.rs +984 -0
  107. data/ext/itsi_server/src/server/thread_worker.rs +444 -0
  108. data/ext/itsi_server/src/server/tls/locked_dir_cache.rs +132 -0
  109. data/ext/itsi_server/src/server/tls.rs +187 -60
  110. data/ext/itsi_server/src/server/types.rs +43 -0
  111. data/ext/itsi_tracing/Cargo.toml +5 -0
  112. data/ext/itsi_tracing/src/lib.rs +225 -7
  113. data/ext/itsi_tracing/target/debug/incremental/itsi_tracing-0994n8rpvvt9m/s-h510hfz1f6-1kbycmq.lock +0 -0
  114. data/ext/itsi_tracing/target/debug/incremental/itsi_tracing-0bob7bf4yq34i/s-h5113125h5-0lh4rag.lock +0 -0
  115. data/ext/itsi_tracing/target/debug/incremental/itsi_tracing-2fcodulrxbbxo/s-h510h2infk-0hp5kjw.lock +0 -0
  116. data/ext/itsi_tracing/target/debug/incremental/itsi_tracing-2iak63r1woi1l/s-h510h2in4q-0kxfzw1.lock +0 -0
  117. data/ext/itsi_tracing/target/debug/incremental/itsi_tracing-2kk4qj9gn5dg2/s-h5113124kv-0enwon2.lock +0 -0
  118. data/ext/itsi_tracing/target/debug/incremental/itsi_tracing-2mwo0yas7dtw4/s-h510hfz1ha-1udgpei.lock +0 -0
  119. data/lib/itsi/http_request.rb +87 -0
  120. data/lib/itsi/http_response.rb +39 -0
  121. data/lib/itsi/server/Itsi.rb +119 -0
  122. data/lib/itsi/server/config/dsl.rb +506 -0
  123. data/lib/itsi/server/config.rb +131 -0
  124. data/lib/itsi/server/default_app/default_app.rb +38 -0
  125. data/lib/itsi/server/default_app/index.html +91 -0
  126. data/lib/itsi/server/grpc_interface.rb +213 -0
  127. data/lib/itsi/server/rack/handler/itsi.rb +27 -0
  128. data/lib/itsi/server/rack_interface.rb +94 -0
  129. data/lib/itsi/server/scheduler_interface.rb +21 -0
  130. data/lib/itsi/server/scheduler_mode.rb +10 -0
  131. data/lib/itsi/server/signal_trap.rb +29 -0
  132. data/lib/itsi/server/version.rb +1 -1
  133. data/lib/itsi/server.rb +90 -9
  134. data/lib/itsi/standard_headers.rb +86 -0
  135. metadata +122 -31
  136. data/ext/itsi_server/src/request/itsi_request.rs +0 -143
  137. data/ext/itsi_server/src/request/mod.rs +0 -1
  138. data/ext/itsi_server/src/server/itsi_ca/itsi_ca.crt +0 -32
  139. data/ext/itsi_server/src/server/itsi_ca/itsi_ca.key +0 -52
  140. data/ext/itsi_server/src/server/itsi_server.rs +0 -182
  141. data/ext/itsi_server/src/server/transfer_protocol.rs +0 -23
  142. data/ext/itsi_server/src/stream_writer/mod.rs +0 -21
  143. data/lib/itsi/request.rb +0 -39
@@ -0,0 +1,229 @@
1
+ use super::serve_strategy::{cluster_mode::ClusterMode, single_mode::SingleMode};
2
+ use itsi_error::{ItsiError, Result};
3
+ use itsi_rb_helpers::{call_with_gvl, call_without_gvl, create_ruby_thread, fork};
4
+ use itsi_tracing::error;
5
+ use nix::{
6
+ errno::Errno,
7
+ sys::{
8
+ signal::{
9
+ kill,
10
+ Signal::{SIGKILL, SIGTERM, SIGUSR2},
11
+ },
12
+ wait::{waitpid, WaitPidFlag, WaitStatus},
13
+ },
14
+ unistd::{setpgid, Pid},
15
+ };
16
+ use parking_lot::Mutex;
17
+ use std::{
18
+ process::{self, exit},
19
+ sync::Arc,
20
+ time::{Duration, Instant},
21
+ };
22
+ use sysinfo::System;
23
+
24
+ use tokio::{sync::watch, time::sleep};
25
+ use tracing::{info, instrument, warn};
26
+
27
+ #[derive(Clone, Debug)]
28
+ pub struct ProcessWorker {
29
+ pub worker_id: usize,
30
+ pub child_pid: Arc<Mutex<Option<Pid>>>,
31
+ pub started_at: Instant,
32
+ }
33
+
34
+ impl Default for ProcessWorker {
35
+ fn default() -> Self {
36
+ Self {
37
+ worker_id: 0,
38
+ child_pid: Arc::new(Mutex::new(None)),
39
+ started_at: Instant::now(),
40
+ }
41
+ }
42
+ }
43
+
44
+ impl ProcessWorker {
45
+ #[instrument(skip(self, cluster_template), fields(self.worker_id = %self.worker_id))]
46
+ pub(crate) fn boot(&self, cluster_template: Arc<ClusterMode>) -> Result<()> {
47
+ let child_pid = *self.child_pid.lock();
48
+ if let Some(pid) = child_pid {
49
+ if self.is_alive() {
50
+ if let Err(e) = kill(pid, SIGTERM) {
51
+ info!("Failed to send SIGTERM to process {}: {}", pid, e);
52
+ }
53
+ }
54
+ *self.child_pid.lock() = None;
55
+ }
56
+
57
+ match call_with_gvl(|_ruby| {
58
+ fork(
59
+ cluster_template
60
+ .server_config
61
+ .server_params
62
+ .read()
63
+ .hooks
64
+ .get("after_fork")
65
+ .cloned(),
66
+ )
67
+ }) {
68
+ Some(pid) => {
69
+ *self.child_pid.lock() = Some(Pid::from_raw(pid));
70
+ }
71
+ None => {
72
+ if let Err(e) = setpgid(
73
+ Pid::from_raw(process::id() as i32),
74
+ Pid::from_raw(process::id() as i32),
75
+ ) {
76
+ error!("Failed to set process group ID: {}", e);
77
+ }
78
+ match SingleMode::new(cluster_template.server_config.clone()) {
79
+ Ok(single_mode) => {
80
+ Arc::new(single_mode).run().ok();
81
+ }
82
+ Err(e) => {
83
+ error!("Failed to boot into worker mode: {}", e);
84
+ }
85
+ }
86
+ exit(0)
87
+ }
88
+ }
89
+ Ok(())
90
+ }
91
+
92
+ pub fn pid(&self) -> i32 {
93
+ if let Some(pid) = *self.child_pid.lock() {
94
+ return pid.as_raw();
95
+ }
96
+ 0
97
+ }
98
+
99
+ pub(crate) fn memory_usage(&self) -> Option<u64> {
100
+ if let Some(pid) = *self.child_pid.lock() {
101
+ let s = System::new_all();
102
+ if let Some(process) = s.process(sysinfo::Pid::from(pid.as_raw() as usize)) {
103
+ return Some(process.memory());
104
+ }
105
+ }
106
+ None
107
+ }
108
+
109
+ pub(crate) async fn reboot(&self, cluster_template: Arc<ClusterMode>) -> Result<bool> {
110
+ self.graceful_shutdown(cluster_template.clone()).await;
111
+ let self_clone = self.clone();
112
+ let (booted_sender, mut booted_receiver) = watch::channel(false);
113
+ create_ruby_thread(move || {
114
+ call_without_gvl(move || {
115
+ if self_clone.boot(cluster_template).is_ok() {
116
+ booted_sender.send(true).ok()
117
+ } else {
118
+ booted_sender.send(false).ok()
119
+ };
120
+ })
121
+ });
122
+
123
+ booted_receiver
124
+ .changed()
125
+ .await
126
+ .map_err(|_| ItsiError::InternalServerError("Failed to boot worker".to_owned()))?;
127
+
128
+ let guard = booted_receiver.borrow();
129
+ let result = guard.to_owned();
130
+ // Not very robust, we should check to see if the worker is actually listening before considering this successful.
131
+ sleep(Duration::from_secs(1)).await;
132
+ Ok(result)
133
+ }
134
+
135
+ pub(crate) async fn graceful_shutdown(&self, cluster_template: Arc<ClusterMode>) {
136
+ let self_clone = self.clone();
137
+ self_clone.request_shutdown();
138
+ let force_kill_time = Instant::now()
139
+ + Duration::from_secs_f64(
140
+ cluster_template
141
+ .server_config
142
+ .server_params
143
+ .read()
144
+ .shutdown_timeout,
145
+ );
146
+ while self_clone.is_alive() && force_kill_time > Instant::now() {
147
+ tokio::time::sleep(Duration::from_millis(100)).await;
148
+ }
149
+ if self_clone.is_alive() {
150
+ self_clone.force_kill();
151
+ }
152
+ }
153
+
154
+ pub(crate) fn boot_if_dead(&self, cluster_template: Arc<ClusterMode>) -> bool {
155
+ if !self.is_alive() {
156
+ if self.just_started() {
157
+ error!(
158
+ "Worker in crash loop {:?}. Refusing to restart",
159
+ self.child_pid.lock()
160
+ );
161
+ return false;
162
+ } else {
163
+ let self_clone = self.clone();
164
+ create_ruby_thread(move || {
165
+ call_without_gvl(move || {
166
+ self_clone.boot(cluster_template).ok();
167
+ })
168
+ });
169
+ }
170
+ }
171
+ true
172
+ }
173
+
174
+ pub(crate) fn request_shutdown(&self) {
175
+ let child_pid = *self.child_pid.lock();
176
+ if let Some(pid) = child_pid {
177
+ if let Err(e) = kill(pid, SIGTERM) {
178
+ error!("Failed to send SIGTERM to process {}: {}", pid, e);
179
+ }
180
+ }
181
+ }
182
+
183
+ pub(crate) fn force_kill(&self) {
184
+ let child_pid = *self.child_pid.lock();
185
+ if let Some(pid) = child_pid {
186
+ if self.is_alive() {
187
+ if let Err(e) = kill(pid, SIGKILL) {
188
+ error!("Failed to force kill process {}: {}", pid, e);
189
+ }
190
+ }
191
+ }
192
+ }
193
+
194
+ pub fn print_info(&self) -> Result<()> {
195
+ let child_pid = *self.child_pid.lock();
196
+ if let Some(pid) = child_pid {
197
+ println!("Worker {:?}, PID: {:?}", self.worker_id, pid);
198
+ if let Err(e) = kill(pid, SIGUSR2) {
199
+ error!("Failed to send SIGUSR2 to process {}: {}", pid, e);
200
+ }
201
+ }
202
+
203
+ Ok(())
204
+ }
205
+
206
+ pub(crate) fn just_started(&self) -> bool {
207
+ let now = Instant::now();
208
+ now.duration_since(self.started_at).as_millis() < 2000
209
+ }
210
+
211
+ pub(crate) fn is_alive(&self) -> bool {
212
+ let child_pid = *self.child_pid.lock();
213
+ if let Some(pid) = child_pid {
214
+ match waitpid(pid, Some(WaitPidFlag::WNOHANG)) {
215
+ Ok(WaitStatus::Exited(_, _)) | Ok(WaitStatus::Signaled(_, _, _)) => {
216
+ return false;
217
+ }
218
+ Ok(WaitStatus::StillAlive) | Ok(_) => {}
219
+ Err(_) => return false,
220
+ }
221
+ match kill(pid, None) {
222
+ Ok(_) => true,
223
+ Err(errno) => !matches!(errno, Errno::ESRCH),
224
+ }
225
+ } else {
226
+ false
227
+ }
228
+ }
229
+ }