itsi 0.1.9 → 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.
Files changed (294) hide show
  1. checksums.yaml +4 -4
  2. data/Cargo.lock +1542 -43
  3. data/Itsi.rb +125 -0
  4. data/Rakefile +8 -4
  5. data/crates/itsi_error/src/lib.rs +9 -0
  6. data/crates/itsi_rb_helpers/Cargo.toml +1 -0
  7. data/crates/itsi_rb_helpers/src/heap_value.rs +18 -0
  8. data/crates/itsi_rb_helpers/src/lib.rs +59 -9
  9. data/crates/itsi_server/Cargo.toml +70 -28
  10. data/crates/itsi_server/src/lib.rs +80 -80
  11. data/crates/itsi_server/src/{body_proxy → ruby_types/itsi_body_proxy}/big_bytes.rs +10 -5
  12. data/{gems/server/ext/itsi_server/src/body_proxy/itsi_body_proxy.rs → crates/itsi_server/src/ruby_types/itsi_body_proxy/mod.rs} +22 -3
  13. data/crates/itsi_server/src/ruby_types/itsi_grpc_request.rs +147 -0
  14. data/crates/itsi_server/src/ruby_types/itsi_grpc_response.rs +19 -0
  15. data/crates/itsi_server/src/ruby_types/itsi_grpc_stream/mod.rs +216 -0
  16. data/crates/itsi_server/src/ruby_types/itsi_http_request.rs +282 -0
  17. data/crates/itsi_server/src/{response/itsi_response.rs → ruby_types/itsi_http_response.rs} +72 -41
  18. data/crates/itsi_server/src/ruby_types/itsi_server/file_watcher.rs +225 -0
  19. data/crates/itsi_server/src/ruby_types/itsi_server/itsi_server_config.rs +355 -0
  20. data/crates/itsi_server/src/ruby_types/itsi_server.rs +82 -0
  21. data/crates/itsi_server/src/ruby_types/mod.rs +55 -0
  22. data/crates/itsi_server/src/server/bind.rs +29 -17
  23. data/crates/itsi_server/src/server/byte_frame.rs +32 -0
  24. data/crates/itsi_server/src/server/cache_store.rs +74 -0
  25. data/crates/itsi_server/src/server/itsi_service.rs +172 -0
  26. data/crates/itsi_server/src/server/lifecycle_event.rs +3 -0
  27. data/crates/itsi_server/src/server/listener.rs +111 -11
  28. data/crates/itsi_server/src/server/middleware_stack/middleware.rs +153 -0
  29. data/crates/itsi_server/src/server/middleware_stack/middlewares/allow_list.rs +47 -0
  30. data/crates/itsi_server/src/server/middleware_stack/middlewares/auth_api_key.rs +58 -0
  31. data/crates/itsi_server/src/server/middleware_stack/middlewares/auth_basic.rs +82 -0
  32. data/crates/itsi_server/src/server/middleware_stack/middlewares/auth_jwt.rs +321 -0
  33. data/crates/itsi_server/src/server/middleware_stack/middlewares/cache_control.rs +139 -0
  34. data/crates/itsi_server/src/server/middleware_stack/middlewares/compression.rs +300 -0
  35. data/crates/itsi_server/src/server/middleware_stack/middlewares/cors.rs +287 -0
  36. data/crates/itsi_server/src/server/middleware_stack/middlewares/deny_list.rs +48 -0
  37. data/crates/itsi_server/src/server/middleware_stack/middlewares/error_response.rs +127 -0
  38. data/crates/itsi_server/src/server/middleware_stack/middlewares/etag.rs +191 -0
  39. data/crates/itsi_server/src/server/middleware_stack/middlewares/grpc_service.rs +72 -0
  40. data/crates/itsi_server/src/server/middleware_stack/middlewares/header_interpretation.rs +85 -0
  41. data/crates/itsi_server/src/server/middleware_stack/middlewares/intrusion_protection.rs +195 -0
  42. data/crates/itsi_server/src/server/middleware_stack/middlewares/log_requests.rs +82 -0
  43. data/crates/itsi_server/src/server/middleware_stack/middlewares/mod.rs +82 -0
  44. data/crates/itsi_server/src/server/middleware_stack/middlewares/proxy.rs +216 -0
  45. data/crates/itsi_server/src/server/middleware_stack/middlewares/rate_limit.rs +124 -0
  46. data/crates/itsi_server/src/server/middleware_stack/middlewares/redirect.rs +76 -0
  47. data/crates/itsi_server/src/server/middleware_stack/middlewares/request_headers.rs +43 -0
  48. data/crates/itsi_server/src/server/middleware_stack/middlewares/response_headers.rs +34 -0
  49. data/crates/itsi_server/src/server/middleware_stack/middlewares/ruby_app.rs +93 -0
  50. data/crates/itsi_server/src/server/middleware_stack/middlewares/static_assets.rs +162 -0
  51. data/crates/itsi_server/src/server/middleware_stack/middlewares/string_rewrite.rs +158 -0
  52. data/crates/itsi_server/src/server/middleware_stack/middlewares/token_source.rs +12 -0
  53. data/crates/itsi_server/src/server/middleware_stack/mod.rs +315 -0
  54. data/crates/itsi_server/src/server/mod.rs +8 -1
  55. data/crates/itsi_server/src/server/process_worker.rs +44 -11
  56. data/crates/itsi_server/src/server/rate_limiter.rs +565 -0
  57. data/crates/itsi_server/src/server/request_job.rs +11 -0
  58. data/crates/itsi_server/src/server/serve_strategy/cluster_mode.rs +129 -46
  59. data/crates/itsi_server/src/server/serve_strategy/mod.rs +9 -6
  60. data/crates/itsi_server/src/server/serve_strategy/single_mode.rs +325 -167
  61. data/crates/itsi_server/src/server/signal.rs +20 -4
  62. data/crates/itsi_server/src/server/static_file_server.rs +984 -0
  63. data/crates/itsi_server/src/server/thread_worker.rs +165 -88
  64. data/crates/itsi_server/src/server/tls.rs +1 -1
  65. data/crates/itsi_server/src/server/types.rs +43 -0
  66. data/crates/itsi_server/test.md +14 -0
  67. data/crates/itsi_tracing/Cargo.toml +1 -0
  68. data/crates/itsi_tracing/src/lib.rs +216 -45
  69. data/docs/.gitignore +7 -0
  70. data/docs/.gitpod.yml +15 -0
  71. data/docs/Itsi.rb +17 -0
  72. data/docs/content/_index.md +17 -0
  73. data/docs/content/about.md +6 -0
  74. data/docs/content/docs/_index.md +18 -0
  75. data/docs/content/docs/first-page.md +9 -0
  76. data/docs/content/docs/folder/_index.md +10 -0
  77. data/docs/content/docs/folder/leaf.md +7 -0
  78. data/docs/go.mod +5 -0
  79. data/docs/go.sum +2 -0
  80. data/docs/hugo.yaml +77 -0
  81. data/examples/static_assets_example.rb +83 -0
  82. data/gems/_index.md +18 -0
  83. data/gems/scheduler/CODE_OF_CONDUCT.md +7 -0
  84. data/gems/scheduler/Cargo.lock +75 -14
  85. data/gems/scheduler/README.md +5 -0
  86. data/gems/scheduler/_index.md +7 -0
  87. data/gems/scheduler/itsi-scheduler.gemspec +4 -1
  88. data/gems/scheduler/lib/itsi/scheduler/version.rb +1 -1
  89. data/gems/scheduler/lib/itsi/scheduler.rb +2 -2
  90. data/gems/scheduler/test/test_file_io.rb +0 -1
  91. data/gems/scheduler/test/test_itsi_scheduler.rb +1 -1
  92. data/gems/server/CHANGELOG.md +5 -0
  93. data/gems/server/CODE_OF_CONDUCT.md +7 -0
  94. data/gems/server/Cargo.lock +1543 -43
  95. data/gems/server/README.md +4 -0
  96. data/gems/server/_index.md +6 -0
  97. data/gems/server/exe/itsi +46 -57
  98. data/gems/server/itsi-server.gemspec +3 -2
  99. data/gems/server/lib/itsi/{request.rb → http_request.rb} +29 -5
  100. data/gems/server/lib/itsi/http_response.rb +39 -0
  101. data/gems/server/lib/itsi/server/Itsi.rb +119 -0
  102. data/gems/server/lib/itsi/server/config/dsl.rb +506 -0
  103. data/gems/server/lib/itsi/server/config.rb +131 -0
  104. data/gems/server/lib/itsi/server/default_app/default_app.rb +38 -0
  105. data/gems/server/lib/itsi/server/grpc_interface.rb +213 -0
  106. data/gems/server/lib/itsi/server/rack/handler/itsi.rb +9 -6
  107. data/gems/server/lib/itsi/server/rack_interface.rb +24 -9
  108. data/gems/server/lib/itsi/server/scheduler_interface.rb +1 -1
  109. data/gems/server/lib/itsi/server/scheduler_mode.rb +4 -0
  110. data/gems/server/lib/itsi/server/signal_trap.rb +6 -1
  111. data/gems/server/lib/itsi/server/version.rb +1 -1
  112. data/gems/server/lib/itsi/server.rb +75 -60
  113. data/gems/server/lib/itsi/standard_headers.rb +86 -0
  114. data/gems/server/test/helpers/test_helper.rb +14 -12
  115. data/gems/server/test/test_itsi_server.rb +21 -2
  116. data/lib/itsi/version.rb +1 -1
  117. data/sandbox/itsi_file/Gemfile +11 -0
  118. data/sandbox/itsi_file/Gemfile.lock +69 -0
  119. data/sandbox/itsi_file/Itsi.rb +276 -0
  120. data/sandbox/itsi_file/error.html +2 -0
  121. data/sandbox/itsi_file/organisations_controller.rb +20 -0
  122. data/sandbox/itsi_file/public/assets/image.png +0 -0
  123. data/sandbox/itsi_file/public/assets/index.html +1 -0
  124. data/sandbox/itsi_sandbox_async/Gemfile +1 -1
  125. data/sandbox/itsi_sandbox_hanami/Gemfile.lock +2 -2
  126. data/sandbox/itsi_sandbox_rack/Gemfile.lock +2 -2
  127. data/sandbox/itsi_sandbox_rack/config.ru +2 -15
  128. data/sandbox/itsi_sandbox_rails/.dockerignore +2 -5
  129. data/sandbox/itsi_sandbox_rails/.github/workflows/ci.yml +1 -1
  130. data/sandbox/itsi_sandbox_rails/.gitignore +2 -1
  131. data/sandbox/itsi_sandbox_rails/Dockerfile +6 -9
  132. data/sandbox/itsi_sandbox_rails/Gemfile +16 -22
  133. data/sandbox/itsi_sandbox_rails/Gemfile.lock +100 -225
  134. data/sandbox/itsi_sandbox_rails/app/assets/config/manifest.js +4 -0
  135. data/sandbox/itsi_sandbox_rails/app/assets/stylesheets/application.css +11 -6
  136. data/sandbox/itsi_sandbox_rails/app/channels/application_cable/channel.rb +4 -0
  137. data/sandbox/itsi_sandbox_rails/app/channels/application_cable/connection.rb +4 -0
  138. data/sandbox/itsi_sandbox_rails/app/controllers/live_controller.rb +7 -8
  139. data/sandbox/itsi_sandbox_rails/app/controllers/uploads_controller.rb +0 -3
  140. data/sandbox/itsi_sandbox_rails/app/views/layouts/application.html.erb +2 -7
  141. data/sandbox/itsi_sandbox_rails/bin/docker-entrypoint +3 -4
  142. data/sandbox/itsi_sandbox_rails/bin/setup +8 -5
  143. data/sandbox/itsi_sandbox_rails/config/application.rb +1 -35
  144. data/sandbox/itsi_sandbox_rails/config/cable.yml +3 -10
  145. data/sandbox/itsi_sandbox_rails/config/credentials.yml.enc +1 -1
  146. data/sandbox/itsi_sandbox_rails/config/database.yml +9 -19
  147. data/sandbox/itsi_sandbox_rails/config/environment.rb +1 -1
  148. data/sandbox/itsi_sandbox_rails/config/environments/development.rb +21 -12
  149. data/sandbox/itsi_sandbox_rails/config/environments/production.rb +49 -34
  150. data/sandbox/itsi_sandbox_rails/config/environments/test.rb +19 -5
  151. data/sandbox/itsi_sandbox_rails/config/initializers/assets.rb +5 -0
  152. data/sandbox/itsi_sandbox_rails/config/initializers/filter_parameter_logging.rb +1 -1
  153. data/sandbox/itsi_sandbox_rails/config/initializers/permissions_policy.rb +13 -0
  154. data/sandbox/itsi_sandbox_rails/config/puma.rb +2 -9
  155. data/sandbox/itsi_sandbox_rails/config.ru +0 -1
  156. data/sandbox/itsi_sandbox_rails/db/migrate/20250301041554_create_posts.rb +1 -1
  157. data/sandbox/itsi_sandbox_rails/db/schema.rb +2 -2
  158. data/sandbox/itsi_sandbox_rails/lib/assets/.keep +0 -0
  159. data/sandbox/itsi_sandbox_rails/public/404.html +66 -113
  160. data/sandbox/itsi_sandbox_rails/public/406-unsupported-browser.html +65 -113
  161. data/sandbox/itsi_sandbox_rails/public/422.html +66 -113
  162. data/sandbox/itsi_sandbox_rails/public/500.html +65 -113
  163. data/sandbox/itsi_sandbox_rails/public/icon.png +0 -0
  164. data/sandbox/itsi_sandbox_rails/public/icon.svg +2 -2
  165. data/sandbox/itsi_sandbox_rails/test/channels/application_cable/connection_test.rb +13 -0
  166. data/sandbox/itsi_sandbox_roda/Gemfile.lock +3 -10
  167. data/tasks.txt +72 -12
  168. metadata +94 -139
  169. data/crates/itsi_server/src/body_proxy/itsi_body_proxy.rs +0 -122
  170. data/crates/itsi_server/src/body_proxy/mod.rs +0 -2
  171. data/crates/itsi_server/src/request/itsi_request.rs +0 -305
  172. data/crates/itsi_server/src/request/mod.rs +0 -1
  173. data/crates/itsi_server/src/response/mod.rs +0 -1
  174. data/crates/itsi_server/src/server/itsi_server.rs +0 -294
  175. data/gems/scheduler/ext/itsi_error/Cargo.lock +0 -368
  176. data/gems/scheduler/ext/itsi_error/Cargo.toml +0 -11
  177. data/gems/scheduler/ext/itsi_error/src/from.rs +0 -68
  178. data/gems/scheduler/ext/itsi_error/src/lib.rs +0 -24
  179. data/gems/scheduler/ext/itsi_instrument_entry/Cargo.toml +0 -15
  180. data/gems/scheduler/ext/itsi_instrument_entry/src/lib.rs +0 -31
  181. data/gems/scheduler/ext/itsi_rb_helpers/Cargo.lock +0 -355
  182. data/gems/scheduler/ext/itsi_rb_helpers/Cargo.toml +0 -10
  183. data/gems/scheduler/ext/itsi_rb_helpers/src/heap_value.rs +0 -121
  184. data/gems/scheduler/ext/itsi_rb_helpers/src/lib.rs +0 -178
  185. data/gems/scheduler/ext/itsi_scheduler/Cargo.toml +0 -24
  186. data/gems/scheduler/ext/itsi_scheduler/extconf.rb +0 -6
  187. data/gems/scheduler/ext/itsi_scheduler/src/itsi_scheduler/io_helpers.rs +0 -56
  188. data/gems/scheduler/ext/itsi_scheduler/src/itsi_scheduler/io_waiter.rs +0 -44
  189. data/gems/scheduler/ext/itsi_scheduler/src/itsi_scheduler/timer.rs +0 -44
  190. data/gems/scheduler/ext/itsi_scheduler/src/itsi_scheduler.rs +0 -308
  191. data/gems/scheduler/ext/itsi_scheduler/src/lib.rs +0 -38
  192. data/gems/scheduler/ext/itsi_server/Cargo.lock +0 -2956
  193. data/gems/scheduler/ext/itsi_server/Cargo.toml +0 -47
  194. data/gems/scheduler/ext/itsi_server/extconf.rb +0 -6
  195. data/gems/scheduler/ext/itsi_server/src/body_proxy/big_bytes.rs +0 -104
  196. data/gems/scheduler/ext/itsi_server/src/body_proxy/itsi_body_proxy.rs +0 -122
  197. data/gems/scheduler/ext/itsi_server/src/body_proxy/mod.rs +0 -2
  198. data/gems/scheduler/ext/itsi_server/src/env.rs +0 -43
  199. data/gems/scheduler/ext/itsi_server/src/lib.rs +0 -112
  200. data/gems/scheduler/ext/itsi_server/src/request/itsi_request.rs +0 -305
  201. data/gems/scheduler/ext/itsi_server/src/request/mod.rs +0 -1
  202. data/gems/scheduler/ext/itsi_server/src/response/itsi_response.rs +0 -357
  203. data/gems/scheduler/ext/itsi_server/src/response/mod.rs +0 -1
  204. data/gems/scheduler/ext/itsi_server/src/server/bind.rs +0 -170
  205. data/gems/scheduler/ext/itsi_server/src/server/bind_protocol.rs +0 -37
  206. data/gems/scheduler/ext/itsi_server/src/server/io_stream.rs +0 -104
  207. data/gems/scheduler/ext/itsi_server/src/server/itsi_server.rs +0 -294
  208. data/gems/scheduler/ext/itsi_server/src/server/lifecycle_event.rs +0 -9
  209. data/gems/scheduler/ext/itsi_server/src/server/listener.rs +0 -318
  210. data/gems/scheduler/ext/itsi_server/src/server/mod.rs +0 -11
  211. data/gems/scheduler/ext/itsi_server/src/server/process_worker.rs +0 -196
  212. data/gems/scheduler/ext/itsi_server/src/server/serve_strategy/cluster_mode.rs +0 -254
  213. data/gems/scheduler/ext/itsi_server/src/server/serve_strategy/mod.rs +0 -27
  214. data/gems/scheduler/ext/itsi_server/src/server/serve_strategy/single_mode.rs +0 -263
  215. data/gems/scheduler/ext/itsi_server/src/server/signal.rs +0 -77
  216. data/gems/scheduler/ext/itsi_server/src/server/thread_worker.rs +0 -367
  217. data/gems/scheduler/ext/itsi_server/src/server/tls/locked_dir_cache.rs +0 -132
  218. data/gems/scheduler/ext/itsi_server/src/server/tls.rs +0 -265
  219. data/gems/scheduler/ext/itsi_tracing/Cargo.lock +0 -274
  220. data/gems/scheduler/ext/itsi_tracing/Cargo.toml +0 -16
  221. data/gems/scheduler/ext/itsi_tracing/src/lib.rs +0 -58
  222. data/gems/server/ext/itsi_error/Cargo.lock +0 -368
  223. data/gems/server/ext/itsi_error/Cargo.toml +0 -11
  224. data/gems/server/ext/itsi_error/src/from.rs +0 -68
  225. data/gems/server/ext/itsi_error/src/lib.rs +0 -24
  226. data/gems/server/ext/itsi_instrument_entry/Cargo.toml +0 -15
  227. data/gems/server/ext/itsi_instrument_entry/src/lib.rs +0 -31
  228. data/gems/server/ext/itsi_rb_helpers/Cargo.lock +0 -355
  229. data/gems/server/ext/itsi_rb_helpers/Cargo.toml +0 -10
  230. data/gems/server/ext/itsi_rb_helpers/src/heap_value.rs +0 -121
  231. data/gems/server/ext/itsi_rb_helpers/src/lib.rs +0 -178
  232. data/gems/server/ext/itsi_scheduler/Cargo.toml +0 -24
  233. data/gems/server/ext/itsi_scheduler/extconf.rb +0 -6
  234. data/gems/server/ext/itsi_scheduler/src/itsi_scheduler/io_helpers.rs +0 -56
  235. data/gems/server/ext/itsi_scheduler/src/itsi_scheduler/io_waiter.rs +0 -44
  236. data/gems/server/ext/itsi_scheduler/src/itsi_scheduler/timer.rs +0 -44
  237. data/gems/server/ext/itsi_scheduler/src/itsi_scheduler.rs +0 -308
  238. data/gems/server/ext/itsi_scheduler/src/lib.rs +0 -38
  239. data/gems/server/ext/itsi_server/Cargo.lock +0 -2956
  240. data/gems/server/ext/itsi_server/Cargo.toml +0 -47
  241. data/gems/server/ext/itsi_server/extconf.rb +0 -6
  242. data/gems/server/ext/itsi_server/src/body_proxy/big_bytes.rs +0 -104
  243. data/gems/server/ext/itsi_server/src/body_proxy/mod.rs +0 -2
  244. data/gems/server/ext/itsi_server/src/env.rs +0 -43
  245. data/gems/server/ext/itsi_server/src/lib.rs +0 -112
  246. data/gems/server/ext/itsi_server/src/request/itsi_request.rs +0 -305
  247. data/gems/server/ext/itsi_server/src/request/mod.rs +0 -1
  248. data/gems/server/ext/itsi_server/src/response/itsi_response.rs +0 -357
  249. data/gems/server/ext/itsi_server/src/response/mod.rs +0 -1
  250. data/gems/server/ext/itsi_server/src/server/bind.rs +0 -170
  251. data/gems/server/ext/itsi_server/src/server/bind_protocol.rs +0 -37
  252. data/gems/server/ext/itsi_server/src/server/io_stream.rs +0 -104
  253. data/gems/server/ext/itsi_server/src/server/itsi_server.rs +0 -294
  254. data/gems/server/ext/itsi_server/src/server/lifecycle_event.rs +0 -9
  255. data/gems/server/ext/itsi_server/src/server/listener.rs +0 -318
  256. data/gems/server/ext/itsi_server/src/server/mod.rs +0 -11
  257. data/gems/server/ext/itsi_server/src/server/process_worker.rs +0 -196
  258. data/gems/server/ext/itsi_server/src/server/serve_strategy/cluster_mode.rs +0 -254
  259. data/gems/server/ext/itsi_server/src/server/serve_strategy/mod.rs +0 -27
  260. data/gems/server/ext/itsi_server/src/server/serve_strategy/single_mode.rs +0 -263
  261. data/gems/server/ext/itsi_server/src/server/signal.rs +0 -77
  262. data/gems/server/ext/itsi_server/src/server/thread_worker.rs +0 -367
  263. data/gems/server/ext/itsi_server/src/server/tls/locked_dir_cache.rs +0 -132
  264. data/gems/server/ext/itsi_server/src/server/tls.rs +0 -265
  265. data/gems/server/ext/itsi_tracing/Cargo.lock +0 -274
  266. data/gems/server/ext/itsi_tracing/Cargo.toml +0 -16
  267. data/gems/server/ext/itsi_tracing/src/lib.rs +0 -58
  268. data/gems/server/lib/itsi/stream_io.rb +0 -38
  269. data/sandbox/itsi_sandbox_rails/.kamal/hooks/docker-setup.sample +0 -3
  270. data/sandbox/itsi_sandbox_rails/.kamal/hooks/post-app-boot.sample +0 -3
  271. data/sandbox/itsi_sandbox_rails/.kamal/hooks/post-deploy.sample +0 -14
  272. data/sandbox/itsi_sandbox_rails/.kamal/hooks/post-proxy-reboot.sample +0 -3
  273. data/sandbox/itsi_sandbox_rails/.kamal/hooks/pre-app-boot.sample +0 -3
  274. data/sandbox/itsi_sandbox_rails/.kamal/hooks/pre-build.sample +0 -51
  275. data/sandbox/itsi_sandbox_rails/.kamal/hooks/pre-connect.sample +0 -47
  276. data/sandbox/itsi_sandbox_rails/.kamal/hooks/pre-deploy.sample +0 -109
  277. data/sandbox/itsi_sandbox_rails/.kamal/hooks/pre-proxy-reboot.sample +0 -3
  278. data/sandbox/itsi_sandbox_rails/.kamal/secrets +0 -17
  279. data/sandbox/itsi_sandbox_rails/bin/dev +0 -2
  280. data/sandbox/itsi_sandbox_rails/bin/jobs +0 -6
  281. data/sandbox/itsi_sandbox_rails/bin/kamal +0 -27
  282. data/sandbox/itsi_sandbox_rails/bin/thrust +0 -5
  283. data/sandbox/itsi_sandbox_rails/config/cache.yml +0 -16
  284. data/sandbox/itsi_sandbox_rails/config/deploy.yml +0 -116
  285. data/sandbox/itsi_sandbox_rails/config/queue.yml +0 -18
  286. data/sandbox/itsi_sandbox_rails/config/recurring.yml +0 -10
  287. data/sandbox/itsi_sandbox_rails/db/cable_schema.rb +0 -11
  288. data/sandbox/itsi_sandbox_rails/db/cache_schema.rb +0 -14
  289. data/sandbox/itsi_sandbox_rails/db/queue_schema.rb +0 -129
  290. data/sandbox/itsi_sandbox_rails/public/400.html +0 -114
  291. data/sandbox/itsi_sandbox_rails/test/fixtures/posts.yml +0 -9
  292. data/sandbox/itsi_sandbox_rails/test/models/post_test.rb +0 -7
  293. /data/{sandbox/itsi_sandbox_rails/script/.keep → crates/_index.md} +0 -0
  294. /data/gems/server/lib/itsi/{index.html → server/default_app/index.html} +0 -0
@@ -1,254 +0,0 @@
1
- use crate::server::{
2
- itsi_server::Server, lifecycle_event::LifecycleEvent, listener::Listener,
3
- process_worker::ProcessWorker,
4
- };
5
- use itsi_error::{ItsiError, Result};
6
- use itsi_rb_helpers::{call_without_gvl, create_ruby_thread};
7
- use itsi_tracing::{error, info, warn};
8
- use nix::{
9
- libc::{self, exit},
10
- unistd::Pid,
11
- };
12
-
13
- use std::{
14
- sync::{atomic::AtomicUsize, Arc},
15
- time::{Duration, Instant},
16
- };
17
- use tokio::{
18
- runtime::{Builder as RuntimeBuilder, Runtime},
19
- sync::{broadcast, watch, Mutex},
20
- time::{self, sleep},
21
- };
22
- use tracing::instrument;
23
- pub(crate) struct ClusterMode {
24
- pub listeners: Arc<Vec<Arc<Listener>>>,
25
- pub server: Arc<Server>,
26
- pub process_workers: parking_lot::Mutex<Vec<ProcessWorker>>,
27
- pub lifecycle_channel: broadcast::Sender<LifecycleEvent>,
28
- }
29
-
30
- static WORKER_ID: AtomicUsize = AtomicUsize::new(0);
31
- static CHILD_SIGNAL_SENDER: parking_lot::Mutex<Option<watch::Sender<()>>> =
32
- parking_lot::Mutex::new(None);
33
-
34
- impl ClusterMode {
35
- pub fn new(
36
- server: Arc<Server>,
37
- listeners: Arc<Vec<Arc<Listener>>>,
38
- lifecycle_channel: broadcast::Sender<LifecycleEvent>,
39
- ) -> Self {
40
- if let Some(f) = server.before_fork.lock().take() {
41
- f();
42
- }
43
- let process_workers = (0..server.workers)
44
- .map(|_| ProcessWorker {
45
- worker_id: WORKER_ID.fetch_add(1, std::sync::atomic::Ordering::Relaxed),
46
- ..Default::default()
47
- })
48
- .collect();
49
-
50
- Self {
51
- listeners,
52
- server,
53
- process_workers: parking_lot::Mutex::new(process_workers),
54
- lifecycle_channel,
55
- }
56
- }
57
-
58
- pub fn build_runtime(&self) -> Runtime {
59
- let mut builder: RuntimeBuilder = RuntimeBuilder::new_current_thread();
60
- builder
61
- .thread_name("itsi-server-accept-loop")
62
- .thread_stack_size(3 * 1024 * 1024)
63
- .enable_io()
64
- .enable_time()
65
- .build()
66
- .expect("Failed to build Tokio runtime")
67
- }
68
-
69
- #[allow(clippy::await_holding_lock)]
70
- pub async fn handle_lifecycle_event(
71
- self: Arc<Self>,
72
- lifecycle_event: LifecycleEvent,
73
- ) -> Result<()> {
74
- match lifecycle_event {
75
- LifecycleEvent::Start => Ok(()),
76
- LifecycleEvent::Shutdown => {
77
- self.shutdown().await?;
78
- Ok(())
79
- }
80
- LifecycleEvent::Restart => {
81
- for worker in self.process_workers.lock().iter() {
82
- worker.reboot(self.clone()).await?;
83
- }
84
- Ok(())
85
- }
86
- LifecycleEvent::IncreaseWorkers => {
87
- let mut workers = self.process_workers.lock();
88
- let worker = ProcessWorker {
89
- worker_id: WORKER_ID.fetch_add(1, std::sync::atomic::Ordering::Relaxed),
90
- ..Default::default()
91
- };
92
- let worker_clone = worker.clone();
93
- let self_clone = self.clone();
94
- create_ruby_thread(move || {
95
- call_without_gvl(move || {
96
- worker_clone.boot(self_clone).ok();
97
- })
98
- });
99
- workers.push(worker);
100
- Ok(())
101
- }
102
- LifecycleEvent::DecreaseWorkers => {
103
- let worker = {
104
- let mut workers = self.process_workers.lock();
105
- workers.pop()
106
- };
107
- if let Some(dropped_worker) = worker {
108
- dropped_worker.request_shutdown();
109
- let force_kill_time =
110
- Instant::now() + Duration::from_secs_f64(self.server.shutdown_timeout);
111
- while dropped_worker.is_alive() && force_kill_time > Instant::now() {
112
- tokio::time::sleep(Duration::from_millis(100)).await;
113
- }
114
- if dropped_worker.is_alive() {
115
- dropped_worker.force_kill();
116
- }
117
- };
118
- Ok(())
119
- }
120
- LifecycleEvent::ForceShutdown => {
121
- for worker in self.process_workers.lock().iter() {
122
- worker.force_kill();
123
- }
124
- unsafe { exit(0) };
125
- }
126
- }
127
- }
128
-
129
- pub async fn shutdown(&self) -> Result<()> {
130
- let shutdown_timeout = self.server.shutdown_timeout;
131
- let workers = self.process_workers.lock().clone();
132
-
133
- workers.iter().for_each(|worker| worker.request_shutdown());
134
-
135
- let remaining_children = Arc::new(Mutex::new(workers.len()));
136
- let monitor_handle = {
137
- let remaining_children: Arc<Mutex<usize>> = Arc::clone(&remaining_children);
138
- let mut workers = workers.clone();
139
- tokio::spawn(async move {
140
- loop {
141
- // Check if all workers have exited
142
- let mut remaining = remaining_children.lock().await;
143
- workers.retain(|worker| worker.is_alive());
144
- *remaining = workers.len();
145
- if *remaining == 0 {
146
- break;
147
- }
148
- sleep(Duration::from_millis(100)).await;
149
- }
150
- })
151
- };
152
-
153
- tokio::select! {
154
- _ = monitor_handle => {
155
- info!("All children exited early, exit normally")
156
- }
157
- _ = sleep(Duration::from_secs_f64(shutdown_timeout)) => {
158
- warn!("Graceful shutdown timeout reached, force killing remaining children");
159
- workers.iter().for_each(|worker| worker.force_kill());
160
- }
161
- }
162
-
163
- Err(ItsiError::Break())
164
- }
165
-
166
- pub fn receive_signal(signal: i32) {
167
- match signal {
168
- libc::SIGCHLD => {
169
- CHILD_SIGNAL_SENDER.lock().as_ref().inspect(|i| {
170
- i.send(()).ok();
171
- });
172
- }
173
- _ => {
174
- // Handle other signals
175
- }
176
- }
177
- }
178
-
179
- pub fn stop(&self) -> Result<()> {
180
- unsafe { libc::signal(libc::SIGCHLD, libc::SIG_DFL) };
181
-
182
- for worker in self.process_workers.lock().iter() {
183
- if worker.is_alive() {
184
- worker.force_kill();
185
- }
186
- }
187
-
188
- Ok(())
189
- }
190
-
191
- #[instrument(skip(self), fields(mode = "cluster", pid=format!("{:?}", Pid::this())))]
192
- pub fn run(self: Arc<Self>) -> Result<()> {
193
- info!("Starting in Cluster mode");
194
- self.process_workers
195
- .lock()
196
- .iter()
197
- .try_for_each(|worker| worker.boot(Arc::clone(&self)))?;
198
-
199
- let (sender, mut receiver) = watch::channel(());
200
- *CHILD_SIGNAL_SENDER.lock() = Some(sender);
201
-
202
- unsafe { libc::signal(libc::SIGCHLD, Self::receive_signal as usize) };
203
-
204
- let mut lifecycle_rx = self.lifecycle_channel.subscribe();
205
- let self_ref = self.clone();
206
-
207
- self.build_runtime().block_on(async {
208
- let self_ref = self_ref.clone();
209
- let mut memory_check_interval = time::interval(time::Duration::from_secs(2));
210
- loop {
211
- tokio::select! {
212
- _ = receiver.changed() => {
213
- let mut workers = self_ref.process_workers.lock();
214
- workers.retain(|worker| {
215
- worker.boot_if_dead(Arc::clone(&self_ref))
216
- });
217
- if workers.is_empty() {
218
- warn!("No workers running. Send SIGTTIN to increase worker count");
219
- }
220
- }
221
- _ = memory_check_interval.tick() => {
222
- if let Some(memory_limit) = self_ref.server.worker_memory_limit {
223
- let largest_worker = {
224
- let workers = self_ref.process_workers.lock();
225
- workers.iter().max_by(|wa, wb| wa.memory_usage().cmp(&wb.memory_usage())).cloned()
226
- };
227
- if let Some(largest_worker) = largest_worker {
228
- if let Some(current_mem_usage) = largest_worker.memory_usage(){
229
- if current_mem_usage > memory_limit {
230
- largest_worker.reboot(self_ref.clone()).await.ok();
231
- }
232
- }
233
- }
234
- }
235
- }
236
- lifecycle_event = lifecycle_rx.recv() => match lifecycle_event{
237
- Ok(lifecycle_event) => {
238
- if let Err(e) = self_ref.clone().handle_lifecycle_event(lifecycle_event).await{
239
- match e {
240
- ItsiError::Break() => break,
241
- _ => error!("Error in handle_lifecycle_event {:?}", e)
242
- }
243
- }
244
-
245
- },
246
- Err(e) => error!("Error receiving lifecycle_event: {:?}", e),
247
- }
248
- }
249
- }
250
- });
251
-
252
- Ok(())
253
- }
254
- }
@@ -1,27 +0,0 @@
1
- use cluster_mode::ClusterMode;
2
- use itsi_error::Result;
3
- use single_mode::SingleMode;
4
- use std::sync::Arc;
5
- pub mod cluster_mode;
6
- pub mod single_mode;
7
-
8
- pub(crate) enum ServeStrategy {
9
- Single(Arc<SingleMode>),
10
- Cluster(Arc<ClusterMode>),
11
- }
12
-
13
- impl ServeStrategy {
14
- pub fn run(&self) -> Result<()> {
15
- match self {
16
- ServeStrategy::Single(single_router) => single_router.clone().run(),
17
- ServeStrategy::Cluster(cluster_router) => cluster_router.clone().run(),
18
- }
19
- }
20
-
21
- pub(crate) fn stop(&self) -> Result<()> {
22
- match self {
23
- ServeStrategy::Single(single_router) => single_router.clone().stop(),
24
- ServeStrategy::Cluster(cluster_router) => cluster_router.clone().stop(),
25
- }
26
- }
27
- }
@@ -1,263 +0,0 @@
1
- use crate::{
2
- request::itsi_request::ItsiRequest,
3
- server::{
4
- io_stream::IoStream,
5
- itsi_server::{RequestJob, Server},
6
- lifecycle_event::LifecycleEvent,
7
- listener::{Listener, ListenerInfo},
8
- thread_worker::{build_thread_workers, ThreadWorker},
9
- },
10
- };
11
- use http::Request;
12
- use hyper::{body::Incoming, service::service_fn};
13
- use hyper_util::{
14
- rt::{TokioExecutor, TokioIo, TokioTimer},
15
- server::conn::auto::Builder,
16
- };
17
- use itsi_error::{ItsiError, Result};
18
- use itsi_tracing::{debug, error, info};
19
- use nix::unistd::Pid;
20
- use std::{
21
- num::NonZeroU8,
22
- pin::Pin,
23
- sync::Arc,
24
- time::{Duration, Instant},
25
- };
26
- use tokio::{
27
- runtime::{Builder as RuntimeBuilder, Runtime},
28
- sync::{
29
- broadcast,
30
- watch::{self, Sender},
31
- },
32
- task::JoinSet,
33
- };
34
- use tracing::instrument;
35
-
36
- pub struct SingleMode {
37
- pub executor: Builder<TokioExecutor>,
38
- pub server: Arc<Server>,
39
- pub sender: async_channel::Sender<RequestJob>,
40
- pub(crate) listeners: Arc<Vec<Arc<Listener>>>,
41
- pub(crate) thread_workers: Arc<Vec<ThreadWorker>>,
42
- pub(crate) lifecycle_channel: broadcast::Sender<LifecycleEvent>,
43
- }
44
-
45
- pub enum RunningPhase {
46
- Running,
47
- ShutdownPending,
48
- Shutdown,
49
- }
50
-
51
- impl SingleMode {
52
- #[instrument(parent=None, skip_all, fields(pid=format!("{:?}", Pid::this())))]
53
- pub(crate) fn new(
54
- server: Arc<Server>,
55
- listeners: Arc<Vec<Arc<Listener>>>,
56
- lifecycle_channel: broadcast::Sender<LifecycleEvent>,
57
- ) -> Result<Self> {
58
- let (thread_workers, sender) = build_thread_workers(
59
- Pid::this(),
60
- NonZeroU8::try_from(server.threads).unwrap(),
61
- server.app.clone(),
62
- server.scheduler_class.clone(),
63
- )?;
64
- Ok(Self {
65
- executor: Builder::new(TokioExecutor::new()),
66
- listeners,
67
- server,
68
- sender,
69
- thread_workers,
70
- lifecycle_channel,
71
- })
72
- }
73
-
74
- pub fn build_runtime(&self) -> Runtime {
75
- let mut builder: RuntimeBuilder = RuntimeBuilder::new_current_thread();
76
- builder
77
- .thread_name("itsi-server-accept-loop")
78
- .thread_stack_size(3 * 1024 * 1024)
79
- .enable_io()
80
- .enable_time()
81
- .build()
82
- .expect("Failed to build Tokio runtime")
83
- }
84
-
85
- pub fn stop(&self) -> Result<()> {
86
- self.lifecycle_channel
87
- .send(LifecycleEvent::Shutdown)
88
- .expect("Failed to send shutdown event");
89
- Ok(())
90
- }
91
-
92
- #[instrument(parent=None, skip(self), fields(pid=format!("{}", Pid::this())))]
93
- pub fn run(self: Arc<Self>) -> Result<()> {
94
- let mut listener_task_set = JoinSet::new();
95
- let self_ref = Arc::new(self);
96
- let runtime = self_ref.build_runtime();
97
-
98
- runtime.block_on(async {
99
- let tokio_listeners = self_ref
100
- .listeners
101
- .iter()
102
- .map(|list| Arc::new(list.to_tokio_listener()))
103
- .collect::<Vec<_>>();
104
- let (shutdown_sender, _) = watch::channel::<RunningPhase>(RunningPhase::Running);
105
- for listener in tokio_listeners.iter() {
106
- let mut lifecycle_rx = self_ref.lifecycle_channel.subscribe();
107
- let listener_info = Arc::new(listener.listener_info());
108
- let self_ref = self_ref.clone();
109
- let listener = listener.clone();
110
- let shutdown_sender = shutdown_sender.clone();
111
-
112
-
113
- let listener_clone = listener.clone();
114
- let mut shutdown_receiver = shutdown_sender.clone().subscribe();
115
- let shutdown_receiver_clone = shutdown_receiver.clone();
116
- listener_task_set.spawn(async move {
117
- listener_clone.spawn_state_task(shutdown_receiver_clone).await;
118
- });
119
-
120
- listener_task_set.spawn(async move {
121
- let strategy = self_ref.clone();
122
- loop {
123
- tokio::select! {
124
- accept_result = listener.accept() => match accept_result {
125
- Ok(accept_result) => {
126
- match strategy.serve_connection(accept_result, listener_info.clone(), shutdown_receiver.clone()).await {
127
- Ok(_) => {
128
- debug!("Connection accepted and served");
129
- },
130
- Err(e) => error!("Error in serve_connection {:?}", e)
131
- }
132
- },
133
- Err(e) => debug!("Listener.accept failed {:?}", e),
134
- },
135
- _ = shutdown_receiver.changed() => {
136
- break;
137
- }
138
- lifecycle_event = lifecycle_rx.recv() => match lifecycle_event{
139
- Ok(lifecycle_event) => {
140
- if let Err(e) = strategy.handle_lifecycle_event(lifecycle_event, shutdown_sender.clone()).await{
141
- match e {
142
- ItsiError::Break() => break,
143
- _ => error!("Error in handle_lifecycle_event {:?}", e)
144
- }
145
- }
146
-
147
- },
148
- Err(e) => error!("Error receiving lifecycle_event: {:?}", e),
149
- }
150
- }
151
- }
152
- });
153
-
154
- }
155
-
156
- while let Some(_res) = listener_task_set.join_next().await {}
157
-
158
- });
159
- runtime.shutdown_timeout(Duration::from_millis(100));
160
-
161
- info!("Runtime has shut down");
162
- Ok(())
163
- }
164
-
165
- pub(crate) async fn serve_connection(
166
- &self,
167
- stream: IoStream,
168
- listener: Arc<ListenerInfo>,
169
- shutdown_channel: watch::Receiver<RunningPhase>,
170
- ) -> Result<()> {
171
- let sender_clone = self.sender.clone();
172
- let addr = stream.addr();
173
- let io: TokioIo<Pin<Box<IoStream>>> = TokioIo::new(Box::pin(stream));
174
- let server = self.server.clone();
175
- let executor = self.executor.clone();
176
- let mut shutdown_channel_clone = shutdown_channel.clone();
177
- tokio::spawn(async move {
178
- let server = server.clone();
179
- let mut executor = executor.clone();
180
- let mut binding = executor.http1();
181
- let shutdown_channel = shutdown_channel_clone.clone();
182
- let mut serve = Box::pin(
183
- binding
184
- .timer(TokioTimer::new())
185
- .header_read_timeout(Duration::from_secs(1))
186
- .serve_connection_with_upgrades(
187
- io,
188
- service_fn(move |hyper_request: Request<Incoming>| {
189
- ItsiRequest::process_request(
190
- hyper_request,
191
- sender_clone.clone(),
192
- server.clone(),
193
- listener.clone(),
194
- addr.clone(),
195
- shutdown_channel.clone(),
196
- )
197
- }),
198
- ),
199
- );
200
-
201
- tokio::select! {
202
- // Await the connection finishing naturally.
203
- res = &mut serve => {
204
- match res{
205
- Ok(()) => {
206
- debug!("Connection closed normally")
207
- },
208
- Err(res) => {
209
- debug!("Connection finished with error: {:?}", res)
210
- }
211
- }
212
- serve.as_mut().graceful_shutdown();
213
- },
214
- // A lifecycle event triggers shutdown.
215
- _ = shutdown_channel_clone.changed() => {
216
- // Initiate graceful shutdown.
217
- serve.as_mut().graceful_shutdown();
218
- // Now await the connection to finish shutting down.
219
- if let Err(e) = serve.await {
220
- debug!("Connection shutdown error: {:?}", e);
221
- }
222
- }
223
- }
224
- });
225
- Ok(())
226
- }
227
-
228
- pub async fn handle_lifecycle_event(
229
- &self,
230
- lifecycle_event: LifecycleEvent,
231
- shutdown_sender: Sender<RunningPhase>,
232
- ) -> Result<()> {
233
- info!("Handling lifecycle event: {:?}", lifecycle_event);
234
- if let LifecycleEvent::Shutdown = lifecycle_event {
235
- shutdown_sender.send(RunningPhase::ShutdownPending).ok();
236
- let deadline = Instant::now() + Duration::from_secs_f64(self.server.shutdown_timeout);
237
- for worker in &*self.thread_workers {
238
- worker.request_shutdown().await;
239
- }
240
- while Instant::now() < deadline {
241
- tokio::time::sleep(Duration::from_millis(50)).await;
242
- let alive_threads = self
243
- .thread_workers
244
- .iter()
245
- .filter(|worker| worker.poll_shutdown(deadline))
246
- .count();
247
- if alive_threads == 0 {
248
- break;
249
- }
250
- tokio::time::sleep(Duration::from_millis(200)).await;
251
- }
252
-
253
- info!("Sending shutdown signal");
254
- shutdown_sender.send(RunningPhase::Shutdown).ok();
255
- self.thread_workers.iter().for_each(|worker| {
256
- worker.poll_shutdown(deadline);
257
- });
258
-
259
- return Err(ItsiError::Break());
260
- }
261
- Ok(())
262
- }
263
- }
@@ -1,77 +0,0 @@
1
- use std::sync::{atomic::AtomicI8, LazyLock};
2
-
3
- use nix::libc::{self, sighandler_t};
4
- use tokio::sync::{self, broadcast};
5
-
6
- use super::lifecycle_event::LifecycleEvent;
7
-
8
- pub static SIGNAL_HANDLER_CHANNEL: LazyLock<(
9
- broadcast::Sender<LifecycleEvent>,
10
- broadcast::Receiver<LifecycleEvent>,
11
- )> = LazyLock::new(|| sync::broadcast::channel(5));
12
-
13
- pub fn send_shutdown_event() {
14
- SIGNAL_HANDLER_CHANNEL
15
- .0
16
- .send(LifecycleEvent::Shutdown)
17
- .expect("Failed to send shutdown event");
18
- }
19
-
20
- pub static SIGINT_COUNT: AtomicI8 = AtomicI8::new(0);
21
- fn receive_signal(signum: i32, _: sighandler_t) {
22
- SIGINT_COUNT.fetch_add(-1, std::sync::atomic::Ordering::SeqCst);
23
- match signum {
24
- libc::SIGTERM | libc::SIGINT => {
25
- SIGINT_COUNT.fetch_add(2, std::sync::atomic::Ordering::SeqCst);
26
- if SIGINT_COUNT.load(std::sync::atomic::Ordering::SeqCst) < 2 {
27
- SIGNAL_HANDLER_CHANNEL.0.send(LifecycleEvent::Shutdown).ok();
28
- } else {
29
- // Not messing about. Force shutdown.
30
- SIGNAL_HANDLER_CHANNEL
31
- .0
32
- .send(LifecycleEvent::ForceShutdown)
33
- .ok();
34
- }
35
- }
36
- libc::SIGUSR1 => {
37
- SIGNAL_HANDLER_CHANNEL.0.send(LifecycleEvent::Restart).ok();
38
- }
39
- libc::SIGTTIN => {
40
- SIGNAL_HANDLER_CHANNEL
41
- .0
42
- .send(LifecycleEvent::IncreaseWorkers)
43
- .ok();
44
- }
45
- libc::SIGTTOU => {
46
- SIGNAL_HANDLER_CHANNEL
47
- .0
48
- .send(LifecycleEvent::DecreaseWorkers)
49
- .ok();
50
- }
51
- _ => {}
52
- }
53
- }
54
-
55
- pub fn reset_signal_handlers() -> bool {
56
- SIGINT_COUNT.store(0, std::sync::atomic::Ordering::SeqCst);
57
- unsafe {
58
- libc::signal(libc::SIGTERM, receive_signal as usize);
59
- libc::signal(libc::SIGINT, receive_signal as usize);
60
- libc::signal(libc::SIGUSR1, receive_signal as usize);
61
- libc::signal(libc::SIGUSR2, receive_signal as usize);
62
- libc::signal(libc::SIGTTIN, receive_signal as usize);
63
- libc::signal(libc::SIGTTOU, receive_signal as usize);
64
- }
65
- true
66
- }
67
-
68
- pub fn clear_signal_handlers() {
69
- unsafe {
70
- libc::signal(libc::SIGTERM, libc::SIG_DFL);
71
- libc::signal(libc::SIGINT, libc::SIG_DFL);
72
- libc::signal(libc::SIGUSR1, libc::SIG_DFL);
73
- libc::signal(libc::SIGUSR2, libc::SIG_DFL);
74
- libc::signal(libc::SIGTTIN, libc::SIG_DFL);
75
- libc::signal(libc::SIGTTOU, libc::SIG_DFL);
76
- }
77
- }