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,33 +1,43 @@
1
1
  use crate::{
2
- request::itsi_request::ItsiRequest,
2
+ ruby_types::itsi_server::itsi_server_config::ItsiServerConfig,
3
3
  server::{
4
4
  io_stream::IoStream,
5
- itsi_server::{RequestJob, Server},
5
+ itsi_service::{IstiServiceInner, ItsiService},
6
6
  lifecycle_event::LifecycleEvent,
7
- listener::{Listener, ListenerInfo},
7
+ listener::ListenerInfo,
8
+ request_job::RequestJob,
9
+ signal::SIGNAL_HANDLER_CHANNEL,
8
10
  thread_worker::{build_thread_workers, ThreadWorker},
9
11
  },
10
12
  };
11
- use http::Request;
12
- use hyper::{body::Incoming, service::service_fn};
13
13
  use hyper_util::{
14
14
  rt::{TokioExecutor, TokioIo, TokioTimer},
15
15
  server::conn::auto::Builder,
16
16
  };
17
17
  use itsi_error::{ItsiError, Result};
18
+ use itsi_rb_helpers::{
19
+ call_with_gvl, call_without_gvl, create_ruby_thread, funcall_no_ret, print_rb_backtrace,
20
+ };
18
21
  use itsi_tracing::{debug, error, info};
22
+ use magnus::value::ReprValue;
19
23
  use nix::unistd::Pid;
24
+ use parking_lot::RwLock;
20
25
  use std::{
26
+ collections::HashMap,
21
27
  num::NonZeroU8,
22
28
  pin::Pin,
23
- sync::Arc,
24
- time::{Duration, Instant},
29
+ sync::{
30
+ atomic::{AtomicBool, Ordering},
31
+ Arc,
32
+ },
33
+ thread::sleep,
34
+ time::{Duration, Instant, SystemTime, UNIX_EPOCH},
25
35
  };
26
36
  use tokio::{
27
37
  runtime::{Builder as RuntimeBuilder, Runtime},
28
38
  sync::{
29
39
  broadcast,
30
- watch::{self, Sender},
40
+ watch::{self},
31
41
  },
32
42
  task::JoinSet,
33
43
  };
@@ -35,11 +45,10 @@ use tracing::instrument;
35
45
 
36
46
  pub struct SingleMode {
37
47
  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>>,
48
+ pub server_config: Arc<ItsiServerConfig>,
42
49
  pub(crate) lifecycle_channel: broadcast::Sender<LifecycleEvent>,
50
+ pub restart_requested: AtomicBool,
51
+ pub status: RwLock<HashMap<u8, (u64, u64)>>,
43
52
  }
44
53
 
45
54
  pub enum RunningPhase {
@@ -49,30 +58,29 @@ pub enum RunningPhase {
49
58
  }
50
59
 
51
60
  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
- )?;
61
+ #[instrument(parent=None, skip_all)]
62
+ pub fn new(server_config: Arc<ItsiServerConfig>) -> Result<Self> {
63
+ server_config.server_params.read().preload_ruby()?;
64
64
  Ok(Self {
65
65
  executor: Builder::new(TokioExecutor::new()),
66
- listeners,
67
- server,
68
- sender,
69
- thread_workers,
70
- lifecycle_channel,
66
+ server_config,
67
+ lifecycle_channel: SIGNAL_HANDLER_CHANNEL.0.clone(),
68
+ restart_requested: AtomicBool::new(false),
69
+ status: RwLock::new(HashMap::new()),
71
70
  })
72
71
  }
73
72
 
74
73
  pub fn build_runtime(&self) -> Runtime {
75
- let mut builder: RuntimeBuilder = RuntimeBuilder::new_current_thread();
74
+ let mut builder: RuntimeBuilder = if self
75
+ .server_config
76
+ .server_params
77
+ .read()
78
+ .multithreaded_reactor
79
+ {
80
+ RuntimeBuilder::new_multi_thread()
81
+ } else {
82
+ RuntimeBuilder::new_current_thread()
83
+ };
76
84
  builder
77
85
  .thread_name("itsi-server-accept-loop")
78
86
  .thread_stack_size(3 * 1024 * 1024)
@@ -83,181 +91,331 @@ impl SingleMode {
83
91
  }
84
92
 
85
93
  pub fn stop(&self) -> Result<()> {
86
- self.lifecycle_channel
87
- .send(LifecycleEvent::Shutdown)
88
- .expect("Failed to send shutdown event");
94
+ self.lifecycle_channel.send(LifecycleEvent::Shutdown).ok();
95
+ Ok(())
96
+ }
97
+
98
+ pub async fn print_info(&self, thread_workers: Arc<Vec<Arc<ThreadWorker>>>) -> Result<()> {
99
+ println!(" └─ Worker");
100
+ println!(
101
+ " - binds: {:?}",
102
+ self.server_config.server_params.read().binds
103
+ );
104
+
105
+ println!(
106
+ " ─ script_name: {:?}",
107
+ self.server_config.server_params.read().script_name
108
+ );
109
+ println!(
110
+ " ─ streaming body: {:?}",
111
+ self.server_config.server_params.read().streamable_body
112
+ );
113
+ println!(
114
+ " ─ multithreaded runtime: {:?}",
115
+ self.server_config
116
+ .server_params
117
+ .read()
118
+ .multithreaded_reactor
119
+ );
120
+ println!(
121
+ " ─ scheduler: {:?}",
122
+ self.server_config.server_params.read().scheduler_class
123
+ );
124
+ println!(
125
+ " ─ OOB GC Response threadhold: {:?}",
126
+ self.server_config
127
+ .server_params
128
+ .read()
129
+ .oob_gc_responses_threshold
130
+ );
131
+ for worker in thread_workers.iter() {
132
+ println!(" └─ - Thread : {:?}", worker.id);
133
+ println!(" - # Requests Processed: {:?}", worker.request_id);
134
+ println!(
135
+ " - Last Request Started: {:?} ago",
136
+ if worker.current_request_start.load(Ordering::Relaxed) == 0 {
137
+ Duration::from_secs(0)
138
+ } else {
139
+ SystemTime::now()
140
+ .duration_since(
141
+ UNIX_EPOCH
142
+ + Duration::from_secs(
143
+ worker.current_request_start.load(Ordering::Relaxed),
144
+ ),
145
+ )
146
+ .unwrap_or(Duration::from_secs(0))
147
+ }
148
+ );
149
+ call_with_gvl(|_| {
150
+ if let Some(thread) = worker.thread.read().as_ref() {
151
+ if let Ok(backtrace) = thread.funcall::<_, _, Vec<String>>("backtrace", ()) {
152
+ println!(" - Backtrace:");
153
+ for line in backtrace {
154
+ println!(" - {}", line);
155
+ }
156
+ }
157
+ }
158
+ })
159
+ }
160
+
89
161
  Ok(())
90
162
  }
91
163
 
92
- #[instrument(parent=None, skip(self), fields(pid=format!("{}", Pid::this())))]
164
+ pub fn start_monitors(
165
+ self: Arc<Self>,
166
+ thread_workers: Arc<Vec<Arc<ThreadWorker>>>,
167
+ ) -> magnus::Thread {
168
+ call_with_gvl(move |_| {
169
+ create_ruby_thread(move || {
170
+ call_without_gvl(move || {
171
+ let monitor_runtime = RuntimeBuilder::new_current_thread()
172
+ .enable_time()
173
+ .build()
174
+ .unwrap();
175
+ let receiver = self.clone();
176
+ monitor_runtime.block_on({
177
+ let mut lifecycle_rx = receiver.lifecycle_channel.subscribe();
178
+ let receiver = receiver.clone();
179
+ let thread_workers = thread_workers.clone();
180
+ async move {
181
+ loop {
182
+ tokio::select! {
183
+ _ = tokio::time::sleep(Duration::from_secs(1)) => {
184
+ let mut status_lock = receiver.status.write();
185
+ thread_workers.iter().for_each(|worker| {
186
+ let worker_entry = status_lock.entry(worker.id);
187
+ let data = (
188
+ worker.request_id.load(Ordering::Relaxed),
189
+ worker.current_request_start.load(Ordering::Relaxed),
190
+ );
191
+ worker_entry.or_insert(data);
192
+ });
193
+ }
194
+ lifecycle_event = lifecycle_rx.recv() => {
195
+ match lifecycle_event {
196
+ Ok(LifecycleEvent::Restart) => {
197
+ receiver.restart().ok();
198
+ }
199
+ Ok(LifecycleEvent::Reload) => {
200
+ receiver.reload().ok();
201
+ }
202
+ Ok(LifecycleEvent::Shutdown) => {
203
+ break;
204
+ }
205
+ Ok(LifecycleEvent::PrintInfo) => {
206
+ receiver.print_info(thread_workers.clone()).await.ok();
207
+ }
208
+ _ => {}
209
+ }
210
+ }
211
+ }
212
+ }
213
+ }
214
+ })
215
+ })
216
+ })
217
+ })
218
+ }
219
+
220
+ #[instrument(name="worker", parent=None, skip(self), fields(pid=format!("{}", Pid::this())))]
93
221
  pub fn run(self: Arc<Self>) -> Result<()> {
94
222
  let mut listener_task_set = JoinSet::new();
95
- let self_ref = Arc::new(self);
96
- let runtime = self_ref.build_runtime();
223
+ let runtime = self.build_runtime();
224
+
225
+ let (thread_workers, job_sender) = build_thread_workers(
226
+ self.server_config.server_params.read().clone(),
227
+ Pid::this(),
228
+ NonZeroU8::try_from(self.server_config.server_params.read().threads).unwrap(),
229
+ )
230
+ .inspect_err(|e| {
231
+ if let Some(err_val) = e.value() {
232
+ print_rb_backtrace(err_val);
233
+ }
234
+ })?;
97
235
 
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();
236
+ info!(
237
+ pid = format!("{}", Pid::this()),
238
+ threads = thread_workers.len(),
239
+ binds = format!("{:?}", self.server_config.server_params.read().binds)
240
+ );
111
241
 
242
+ let (shutdown_sender, _) = watch::channel(RunningPhase::Running);
243
+ let thread = self.clone().start_monitors(thread_workers.clone());
244
+ runtime.block_on(
245
+ async {
246
+ let server_params = self.server_config.server_params.read().clone();
247
+ server_params.middleware.get().unwrap().initialize_layers().await?;
248
+ let tokio_listeners = server_params.listeners.lock()
249
+ .drain(..)
250
+ .map(|list| {
251
+ Arc::new(list.into_tokio_listener())
252
+ })
253
+ .collect::<Vec<_>>();
112
254
 
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
- });
255
+ for listener in tokio_listeners.iter() {
256
+ let mut lifecycle_rx = self.lifecycle_channel.subscribe();
257
+ let listener_info = Arc::new(listener.listener_info());
258
+ let self_ref = self.clone();
259
+ let listener = listener.clone();
260
+ let shutdown_sender = shutdown_sender.clone();
261
+ let job_sender = job_sender.clone();
262
+ let workers_clone = thread_workers.clone();
263
+ let listener_clone = listener.clone();
264
+ let mut shutdown_receiver = shutdown_sender.subscribe();
265
+ let shutdown_receiver_clone = shutdown_receiver.clone();
266
+ listener_task_set.spawn(async move {
267
+ listener_clone.spawn_state_task(shutdown_receiver_clone).await;
268
+ });
119
269
 
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");
270
+ listener_task_set.spawn(async move {
271
+ let strategy_clone = self_ref.clone();
272
+ let mut acceptor_task_set = JoinSet::new();
273
+ loop {
274
+ tokio::select! {
275
+ accept_result = listener.accept() => match accept_result {
276
+ Ok(accept_result) => {
277
+ let strategy = strategy_clone.clone();
278
+ let listener_info = listener_info.clone();
279
+ let shutdown_receiver = shutdown_receiver.clone();
280
+ let job_sender = job_sender.clone();
281
+ acceptor_task_set.spawn(async move {
282
+ strategy.serve_connection(accept_result, job_sender, listener_info, shutdown_receiver).await;
283
+ });
129
284
  },
130
- Err(e) => error!("Error in serve_connection {:?}", e)
285
+ Err(e) => debug!("Listener.accept failed {:?}", e),
286
+ },
287
+ _ = shutdown_receiver.changed() => {
288
+ break;
131
289
  }
132
- },
133
- Err(e) => debug!("Listener.accept failed {:?}", e),
134
- },
135
- _ = shutdown_receiver.changed() => {
136
- break;
290
+ lifecycle_event = lifecycle_rx.recv() => match lifecycle_event{
291
+ Ok(LifecycleEvent::Shutdown) => {
292
+ shutdown_sender.send(RunningPhase::ShutdownPending).unwrap();
293
+ // Tell any in-progress connections to stop accepting new requests
294
+ tokio::time::sleep(Duration::from_millis(25)).await;
295
+ // Tell workers to stop processing requests once they've flushed their buffers.
296
+ for _i in 0..workers_clone.len() {
297
+ job_sender.send(RequestJob::Shutdown).await.unwrap();
298
+ }
299
+ break;
300
+ },
301
+ Err(e) => error!("Error receiving lifecycle_event: {:?}", e),
302
+ _ => {}
303
+ }
137
304
  }
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
305
  }
151
- }
152
- });
306
+ while let Some(_res) = acceptor_task_set.join_next().await {}
307
+ });
153
308
 
154
- }
309
+ }
155
310
 
156
- while let Some(_res) = listener_task_set.join_next().await {}
311
+ while let Some(_res) = listener_task_set.join_next().await {}
312
+
313
+ Ok::<(), ItsiError>(())
314
+ })?;
315
+
316
+ shutdown_sender.send(RunningPhase::Shutdown).ok();
317
+ let deadline = Instant::now()
318
+ + Duration::from_secs_f64(self.server_config.server_params.read().shutdown_timeout);
157
319
 
158
- });
159
320
  runtime.shutdown_timeout(Duration::from_millis(100));
160
321
 
161
- info!("Runtime has shut down");
322
+ loop {
323
+ if thread_workers
324
+ .iter()
325
+ .all(|worker| call_with_gvl(move |_| !worker.poll_shutdown(deadline)))
326
+ {
327
+ funcall_no_ret(thread, "join", ()).ok();
328
+ break;
329
+ }
330
+ sleep(Duration::from_millis(50));
331
+ }
332
+
333
+ if self.restart_requested.load(Ordering::SeqCst) {
334
+ self.restart_requested.store(false, Ordering::SeqCst);
335
+ info!("Worker restarting");
336
+ self.run()?;
337
+ }
338
+ debug!("Runtime has shut down");
162
339
  Ok(())
163
340
  }
164
341
 
165
342
  pub(crate) async fn serve_connection(
166
343
  &self,
167
344
  stream: IoStream,
345
+ job_sender: async_channel::Sender<RequestJob>,
168
346
  listener: Arc<ListenerInfo>,
169
347
  shutdown_channel: watch::Receiver<RunningPhase>,
170
- ) -> Result<()> {
171
- let sender_clone = self.sender.clone();
348
+ ) {
172
349
  let addr = stream.addr();
173
350
  let io: TokioIo<Pin<Box<IoStream>>> = TokioIo::new(Box::pin(stream));
174
- let server = self.server.clone();
175
351
  let executor = self.executor.clone();
176
352
  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
- );
353
+ let mut executor = executor.clone();
354
+ let mut binding = executor.http1();
355
+ let shutdown_channel = shutdown_channel_clone.clone();
200
356
 
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);
357
+ let service = ItsiService {
358
+ inner: Arc::new(IstiServiceInner {
359
+ sender: job_sender.clone(),
360
+ server_params: self.server_config.server_params.read().clone(),
361
+ listener,
362
+ addr: addr.to_string(),
363
+ shutdown_channel: shutdown_channel.clone(),
364
+ }),
365
+ };
366
+ let mut serve = Box::pin(
367
+ binding
368
+ .timer(TokioTimer::new()) // your existing timer
369
+ .header_read_timeout(Duration::from_secs(1))
370
+ .serve_connection_with_upgrades(io, service),
371
+ );
372
+
373
+ tokio::select! {
374
+ // Await the connection finishing naturally.
375
+ res = &mut serve => {
376
+ match res{
377
+ Ok(()) => {
378
+ debug!("Connection closed normally")
379
+ },
380
+ Err(res) => {
381
+ debug!("Connection closed abruptly: {:?}", res)
221
382
  }
222
383
  }
223
- }
224
- });
225
- Ok(())
226
- }
384
+ serve.as_mut().graceful_shutdown();
385
+ },
386
+ // A lifecycle event triggers shutdown.
387
+ _ = shutdown_channel_clone.changed() => {
388
+ // Initiate graceful shutdown.
389
+ info!("Starting graceful shutdown");
390
+ serve.as_mut().graceful_shutdown();
227
391
 
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;
392
+ // Now await the connection to finish shutting down.
393
+ if let Err(e) = serve.await {
394
+ debug!("Connection shutdown error: {:?}", e);
249
395
  }
250
- tokio::time::sleep(Duration::from_millis(200)).await;
251
396
  }
397
+ }
398
+ }
252
399
 
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());
400
+ /// Attempts to reload the config "live"
401
+ /// Not that when running in single mode this will not unload
402
+ /// old code. If you need a clean restart, use the `restart` (SIGUSR2) method instead
403
+ pub fn reload(&self) -> Result<()> {
404
+ let should_reexec = self.server_config.clone().reload(false)?;
405
+ if should_reexec {
406
+ self.server_config.dup_fds()?;
407
+ self.server_config.reload_exec()?;
260
408
  }
409
+ self.restart_requested.store(true, Ordering::SeqCst);
410
+ self.stop()?;
411
+ self.server_config.server_params.read().preload_ruby()?;
412
+ Ok(())
413
+ }
414
+
415
+ /// Restart the server while keeping connections open.
416
+ pub fn restart(&self) -> Result<()> {
417
+ self.server_config.dup_fds()?;
418
+ self.server_config.reload_exec()?;
261
419
  Ok(())
262
420
  }
263
421
  }
@@ -11,10 +11,7 @@ pub static SIGNAL_HANDLER_CHANNEL: LazyLock<(
11
11
  )> = LazyLock::new(|| sync::broadcast::channel(5));
12
12
 
13
13
  pub fn send_shutdown_event() {
14
- SIGNAL_HANDLER_CHANNEL
15
- .0
16
- .send(LifecycleEvent::Shutdown)
17
- .expect("Failed to send shutdown event");
14
+ SIGNAL_HANDLER_CHANNEL.0.send(LifecycleEvent::Shutdown).ok();
18
15
  }
19
16
 
20
17
  pub static SIGINT_COUNT: AtomicI8 = AtomicI8::new(0);
@@ -33,9 +30,18 @@ fn receive_signal(signum: i32, _: sighandler_t) {
33
30
  .ok();
34
31
  }
35
32
  }
33
+ libc::SIGINFO => {
34
+ SIGNAL_HANDLER_CHANNEL
35
+ .0
36
+ .send(LifecycleEvent::PrintInfo)
37
+ .ok();
38
+ }
36
39
  libc::SIGUSR1 => {
37
40
  SIGNAL_HANDLER_CHANNEL.0.send(LifecycleEvent::Restart).ok();
38
41
  }
42
+ libc::SIGUSR2 => {
43
+ SIGNAL_HANDLER_CHANNEL.0.send(LifecycleEvent::Reload).ok();
44
+ }
39
45
  libc::SIGTTIN => {
40
46
  SIGNAL_HANDLER_CHANNEL
41
47
  .0
@@ -48,6 +54,12 @@ fn receive_signal(signum: i32, _: sighandler_t) {
48
54
  .send(LifecycleEvent::DecreaseWorkers)
49
55
  .ok();
50
56
  }
57
+ libc::SIGCHLD => {
58
+ SIGNAL_HANDLER_CHANNEL
59
+ .0
60
+ .send(LifecycleEvent::ChildTerminated)
61
+ .ok();
62
+ }
51
63
  _ => {}
52
64
  }
53
65
  }
@@ -57,10 +69,12 @@ pub fn reset_signal_handlers() -> bool {
57
69
  unsafe {
58
70
  libc::signal(libc::SIGTERM, receive_signal as usize);
59
71
  libc::signal(libc::SIGINT, receive_signal as usize);
72
+ libc::signal(libc::SIGINFO, receive_signal as usize);
60
73
  libc::signal(libc::SIGUSR1, receive_signal as usize);
61
74
  libc::signal(libc::SIGUSR2, receive_signal as usize);
62
75
  libc::signal(libc::SIGTTIN, receive_signal as usize);
63
76
  libc::signal(libc::SIGTTOU, receive_signal as usize);
77
+ libc::signal(libc::SIGCHLD, receive_signal as usize);
64
78
  }
65
79
  true
66
80
  }
@@ -69,9 +83,11 @@ pub fn clear_signal_handlers() {
69
83
  unsafe {
70
84
  libc::signal(libc::SIGTERM, libc::SIG_DFL);
71
85
  libc::signal(libc::SIGINT, libc::SIG_DFL);
86
+ libc::signal(libc::SIGINFO, libc::SIG_DFL);
72
87
  libc::signal(libc::SIGUSR1, libc::SIG_DFL);
73
88
  libc::signal(libc::SIGUSR2, libc::SIG_DFL);
74
89
  libc::signal(libc::SIGTTIN, libc::SIG_DFL);
75
90
  libc::signal(libc::SIGTTOU, libc::SIG_DFL);
91
+ libc::signal(libc::SIGCHLD, libc::SIG_DFL);
76
92
  }
77
93
  }