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,9 +1,8 @@
1
- use super::itsi_server::RequestJob;
2
- use crate::{request::itsi_request::ItsiRequest, ITSI_SERVER};
1
+ use async_channel::Sender;
3
2
  use itsi_rb_helpers::{
4
- call_with_gvl, call_without_gvl, create_ruby_thread, kill_threads, HeapVal, HeapValue,
3
+ call_with_gvl, call_without_gvl, create_ruby_thread, kill_threads, HeapValue,
5
4
  };
6
- use itsi_tracing::{debug, error, info, warn};
5
+ use itsi_tracing::{debug, error, warn};
7
6
  use magnus::{
8
7
  error::Result,
9
8
  value::{InnerValue, Lazy, LazyId, Opaque, ReprValue},
@@ -15,25 +14,34 @@ use std::{
15
14
  num::NonZeroU8,
16
15
  ops::Deref,
17
16
  sync::{
18
- atomic::{AtomicBool, Ordering},
17
+ atomic::{AtomicBool, AtomicU64, Ordering},
19
18
  Arc,
20
19
  },
21
20
  thread,
22
- time::{Duration, Instant},
21
+ time::{Duration, Instant, SystemTime, UNIX_EPOCH},
23
22
  };
24
23
  use tokio::{runtime::Builder as RuntimeBuilder, sync::watch};
25
24
  use tracing::instrument;
25
+
26
+ use crate::ruby_types::{
27
+ itsi_grpc_request::ItsiGrpcRequest, itsi_http_request::ItsiHttpRequest,
28
+ itsi_server::itsi_server_config::ServerParams, ITSI_SERVER,
29
+ };
30
+
31
+ use super::request_job::RequestJob;
26
32
  pub struct ThreadWorker {
27
- pub id: String,
28
- pub app: Opaque<Value>,
33
+ pub params: Arc<ServerParams>,
34
+ pub id: u8,
35
+ pub name: String,
36
+ pub request_id: AtomicU64,
37
+ pub current_request_start: AtomicU64,
29
38
  pub receiver: Arc<async_channel::Receiver<RequestJob>>,
30
- pub sender: async_channel::Sender<RequestJob>,
39
+ pub sender: Sender<RequestJob>,
31
40
  pub thread: RwLock<Option<HeapValue<Thread>>>,
32
41
  pub terminated: Arc<AtomicBool>,
33
42
  pub scheduler_class: Option<Opaque<Value>>,
34
43
  }
35
44
 
36
- static ID_CALL: LazyId = LazyId::new("call");
37
45
  static ID_ALIVE: LazyId = LazyId::new("alive?");
38
46
  static ID_SCHEDULER: LazyId = LazyId::new("scheduler");
39
47
  static ID_SCHEDULE: LazyId = LazyId::new("schedule");
@@ -47,26 +55,26 @@ static CLASS_FIBER: Lazy<RClass> = Lazy::new(|ruby| {
47
55
  });
48
56
 
49
57
  pub struct TerminateWakerSignal(bool);
58
+ type ThreadWorkerBuildResult = Result<(Arc<Vec<Arc<ThreadWorker>>>, Sender<RequestJob>)>;
50
59
 
51
- #[instrument(name = "Boot", parent=None, skip(threads, app, pid, scheduler_class))]
60
+ #[instrument(name = "boot", parent=None, skip(params, threads, pid))]
52
61
  pub fn build_thread_workers(
62
+ params: Arc<ServerParams>,
53
63
  pid: Pid,
54
64
  threads: NonZeroU8,
55
- app: HeapVal,
56
- scheduler_class: Option<String>,
57
- ) -> Result<(Arc<Vec<ThreadWorker>>, async_channel::Sender<RequestJob>)> {
58
- let (sender, receiver) = async_channel::bounded(20);
65
+ ) -> ThreadWorkerBuildResult {
66
+ let (sender, receiver) = async_channel::bounded((threads.get() as u16 * 30) as usize);
59
67
  let receiver_ref = Arc::new(receiver);
60
68
  let sender_ref = sender;
61
- let (app, scheduler_class) = load_app(app, scheduler_class)?;
69
+ let scheduler_class = load_scheduler_class(params.scheduler_class.clone())?;
62
70
  Ok((
63
71
  Arc::new(
64
72
  (1..=u8::from(threads))
65
73
  .map(|id| {
66
- info!(pid = pid.as_raw(), id, "Thread");
67
74
  ThreadWorker::new(
75
+ params.clone(),
76
+ id,
68
77
  format!("{:?}#{:?}", pid, id),
69
- app,
70
78
  receiver_ref.clone(),
71
79
  sender_ref.clone(),
72
80
  scheduler_class,
@@ -78,15 +86,8 @@ pub fn build_thread_workers(
78
86
  ))
79
87
  }
80
88
 
81
- pub fn load_app(
82
- app: HeapVal,
83
- scheduler_class: Option<String>,
84
- ) -> Result<(Opaque<Value>, Option<Opaque<Value>>)> {
89
+ pub fn load_scheduler_class(scheduler_class: Option<String>) -> Result<Option<Opaque<Value>>> {
85
90
  call_with_gvl(|ruby| {
86
- let app = Opaque::from(
87
- app.funcall::<_, _, Value>(*ID_CALL, ())
88
- .expect("Couldn't load app"),
89
- );
90
91
  let scheduler_class = if let Some(scheduler_class) = scheduler_class {
91
92
  Some(Opaque::from(
92
93
  ruby.module_kernel()
@@ -95,76 +96,75 @@ pub fn load_app(
95
96
  } else {
96
97
  None
97
98
  };
98
- Ok((app, scheduler_class))
99
+ Ok(scheduler_class)
99
100
  })
100
101
  }
101
102
  impl ThreadWorker {
102
103
  pub fn new(
103
- id: String,
104
- app: Opaque<Value>,
104
+ params: Arc<ServerParams>,
105
+ id: u8,
106
+ name: String,
105
107
  receiver: Arc<async_channel::Receiver<RequestJob>>,
106
- sender: async_channel::Sender<RequestJob>,
108
+ sender: Sender<RequestJob>,
107
109
  scheduler_class: Option<Opaque<Value>>,
108
- ) -> Result<Self> {
109
- let mut worker = Self {
110
+ ) -> Result<Arc<Self>> {
111
+ let worker = Arc::new(Self {
112
+ params,
110
113
  id,
111
- app,
114
+ request_id: AtomicU64::new(0),
115
+ current_request_start: AtomicU64::new(0),
116
+ name,
112
117
  receiver,
113
118
  sender,
114
119
  thread: RwLock::new(None),
115
120
  terminated: Arc::new(AtomicBool::new(false)),
116
121
  scheduler_class,
117
- };
118
- worker.run()?;
122
+ });
123
+ worker.clone().run()?;
119
124
  Ok(worker)
120
125
  }
121
126
 
122
- #[instrument(skip(self), fields(id = self.id))]
123
- pub async fn request_shutdown(&self) {
124
- match self.sender.send(RequestJob::Shutdown).await {
125
- Ok(_) => {}
126
- Err(err) => error!("Failed to send shutdown request: {}", err),
127
- };
128
- info!("Requesting shutdown");
129
- }
130
-
131
127
  #[instrument(skip(self, deadline), fields(id = self.id))]
132
128
  pub fn poll_shutdown(&self, deadline: Instant) -> bool {
133
- call_with_gvl(|_ruby| {
134
- if let Some(thread) = self.thread.read().deref() {
135
- if Instant::now() > deadline {
136
- warn!("Worker shutdown timed out. Killing thread");
137
- self.terminated.store(true, Ordering::SeqCst);
138
- kill_threads(vec![thread.as_value()]);
139
- }
140
- if thread.funcall::<_, _, bool>(*ID_ALIVE, ()).unwrap_or(false) {
141
- return true;
142
- }
143
- info!("Thread has shut down");
129
+ if let Some(thread) = self.thread.read().deref() {
130
+ if Instant::now() > deadline {
131
+ warn!("Worker shutdown timed out. Killing thread");
132
+ self.terminated.store(true, Ordering::SeqCst);
133
+ kill_threads(vec![thread.as_value()]);
144
134
  }
145
- self.thread.write().take();
135
+ debug!("Checking thread status");
136
+ if thread.funcall::<_, _, bool>(*ID_ALIVE, ()).unwrap_or(false) {
137
+ return true;
138
+ }
139
+ debug!("Thread has shut down");
140
+ }
141
+ self.thread.write().take();
146
142
 
147
- false
148
- })
143
+ false
149
144
  }
150
145
 
151
- pub fn run(&mut self) -> Result<()> {
152
- let id = self.id.clone();
153
- let app = self.app;
146
+ pub fn run(self: Arc<Self>) -> Result<()> {
147
+ let name = self.name.clone();
154
148
  let receiver = self.receiver.clone();
155
149
  let terminated = self.terminated.clone();
156
150
  let scheduler_class = self.scheduler_class;
151
+ let params = self.params.clone();
152
+ let self_ref = self.clone();
157
153
  call_with_gvl(|_| {
158
154
  *self.thread.write() = Some(
159
155
  create_ruby_thread(move || {
160
156
  if let Some(scheduler_class) = scheduler_class {
161
- if let Err(err) =
162
- Self::fiber_accept_loop(id, app, receiver, scheduler_class, terminated)
163
- {
157
+ if let Err(err) = self_ref.fiber_accept_loop(
158
+ params,
159
+ name,
160
+ receiver,
161
+ scheduler_class,
162
+ terminated,
163
+ ) {
164
164
  error!("Error in fiber_accept_loop: {:?}", err);
165
165
  }
166
166
  } else {
167
- Self::accept_loop(id, app, receiver, terminated);
167
+ self_ref.accept_loop(params, name, receiver, terminated);
168
168
  }
169
169
  })
170
170
  .into(),
@@ -175,11 +175,12 @@ impl ThreadWorker {
175
175
  }
176
176
 
177
177
  pub fn build_scheduler_proc(
178
- app: Opaque<Value>,
178
+ self: Arc<Self>,
179
179
  leader: &Arc<Mutex<Option<RequestJob>>>,
180
180
  receiver: &Arc<async_channel::Receiver<RequestJob>>,
181
181
  terminated: &Arc<AtomicBool>,
182
182
  waker_sender: &watch::Sender<TerminateWakerSignal>,
183
+ oob_gc_responses_threshold: Option<u64>,
183
184
  ) -> magnus::block::Proc {
184
185
  let leader = leader.clone();
185
186
  let receiver = receiver.clone();
@@ -196,6 +197,7 @@ impl ThreadWorker {
196
197
  let receiver = receiver.clone();
197
198
  let terminated = terminated.clone();
198
199
  let waker_sender = waker_sender.clone();
200
+ let self_ref = self.clone();
199
201
  let mut batch = Vec::with_capacity(MAX_BATCH_SIZE as usize);
200
202
 
201
203
  static MAX_BATCH_SIZE: i32 = 25;
@@ -203,8 +205,11 @@ impl ThreadWorker {
203
205
  let mut idle_counter = 0;
204
206
  if let Some(v) = leader_clone.lock().take() {
205
207
  match v {
206
- RequestJob::ProcessRequest(itsi_request) => {
207
- batch.push(RequestJob::ProcessRequest(itsi_request))
208
+ RequestJob::ProcessHttpRequest(itsi_request, app_proc) => {
209
+ batch.push(RequestJob::ProcessHttpRequest(itsi_request, app_proc))
210
+ }
211
+ RequestJob::ProcessGrpcRequest(itsi_request, app_proc) => {
212
+ batch.push(RequestJob::ProcessGrpcRequest(itsi_request, app_proc))
208
213
  }
209
214
  RequestJob::Shutdown => {
210
215
  waker_sender.send(TerminateWakerSignal(true)).unwrap();
@@ -223,12 +228,38 @@ impl ThreadWorker {
223
228
  let shutdown_requested = call_with_gvl(|_| {
224
229
  for req in batch.drain(..) {
225
230
  match req {
226
- RequestJob::ProcessRequest(request) => {
231
+ RequestJob::ProcessHttpRequest(request, app_proc) => {
232
+ self_ref.request_id.fetch_add(1, Ordering::Relaxed);
233
+ self_ref.current_request_start.store(
234
+ SystemTime::now()
235
+ .duration_since(UNIX_EPOCH)
236
+ .unwrap()
237
+ .as_secs(),
238
+ Ordering::Relaxed,
239
+ );
227
240
  let response = request.response.clone();
228
- if let Err(err) =
229
- server.funcall::<_, _, Value>(*ID_SCHEDULE, (app, request))
230
- {
231
- ItsiRequest::internal_error(ruby, response, err)
241
+ if let Err(err) = server.funcall::<_, _, Value>(
242
+ *ID_SCHEDULE,
243
+ (app_proc.as_value(), request),
244
+ ) {
245
+ ItsiHttpRequest::internal_error(ruby, response, err)
246
+ }
247
+ }
248
+ RequestJob::ProcessGrpcRequest(request, app_proc) => {
249
+ self_ref.request_id.fetch_add(1, Ordering::Relaxed);
250
+ self_ref.current_request_start.store(
251
+ SystemTime::now()
252
+ .duration_since(UNIX_EPOCH)
253
+ .unwrap()
254
+ .as_secs(),
255
+ Ordering::Relaxed,
256
+ );
257
+ let response = request.stream.clone();
258
+ if let Err(err) = server.funcall::<_, _, Value>(
259
+ *ID_SCHEDULE,
260
+ (app_proc.as_value(), request),
261
+ ) {
262
+ ItsiGrpcRequest::internal_error(ruby, response, err)
232
263
  }
233
264
  }
234
265
  RequestJob::Shutdown => return true,
@@ -243,10 +274,15 @@ impl ThreadWorker {
243
274
  }
244
275
 
245
276
  let yield_result = if receiver.is_empty() {
277
+ let should_gc = if let Some(oob_gc_threshold) = oob_gc_responses_threshold {
278
+ idle_counter = (idle_counter + 1) % oob_gc_threshold;
279
+ idle_counter == 0
280
+ } else {
281
+ false
282
+ };
246
283
  waker_sender.send(TerminateWakerSignal(false)).unwrap();
247
- idle_counter = (idle_counter + 1) % 100;
248
284
  call_with_gvl(|ruby| {
249
- if idle_counter == 0 {
285
+ if should_gc {
250
286
  ruby.gc_start();
251
287
  }
252
288
  scheduler.funcall::<_, _, Value>(*ID_BLOCK, (thread_current, None::<u8>))
@@ -262,10 +298,11 @@ impl ThreadWorker {
262
298
  })
263
299
  }
264
300
 
265
- #[instrument(skip_all, fields(thread_worker=id))]
301
+ #[instrument(skip_all, fields(thread_worker=name))]
266
302
  pub fn fiber_accept_loop(
267
- id: String,
268
- app: Opaque<Value>,
303
+ self: Arc<Self>,
304
+ params: Arc<ServerParams>,
305
+ name: String,
269
306
  receiver: Arc<async_channel::Receiver<RequestJob>>,
270
307
  scheduler_class: Opaque<Value>,
271
308
  terminated: Arc<AtomicBool>,
@@ -273,10 +310,15 @@ impl ThreadWorker {
273
310
  let ruby = Ruby::get().unwrap();
274
311
  let (waker_sender, waker_receiver) = watch::channel(TerminateWakerSignal(false));
275
312
  let leader: Arc<Mutex<Option<RequestJob>>> = Arc::new(Mutex::new(None));
276
- let server = ruby.get_inner(&ITSI_SERVER);
277
- let scheduler_proc =
278
- Self::build_scheduler_proc(app, &leader, &receiver, &terminated, &waker_sender);
279
- let (scheduler, scheduler_fiber) = server.funcall::<_, _, (Value, Value)>(
313
+ let server_class = ruby.get_inner(&ITSI_SERVER);
314
+ let scheduler_proc = self.build_scheduler_proc(
315
+ &leader,
316
+ &receiver,
317
+ &terminated,
318
+ &waker_sender,
319
+ params.oob_gc_responses_threshold,
320
+ );
321
+ let (scheduler, scheduler_fiber) = server_class.funcall::<_, _, (Value, Value)>(
280
322
  "start_scheduler_loop",
281
323
  (scheduler_class, scheduler_proc),
282
324
  )?;
@@ -337,25 +379,60 @@ impl ThreadWorker {
337
379
 
338
380
  #[instrument(skip_all, fields(thread_worker=id))]
339
381
  pub fn accept_loop(
382
+ self: Arc<Self>,
383
+ params: Arc<ServerParams>,
340
384
  id: String,
341
- app: Opaque<Value>,
342
385
  receiver: Arc<async_channel::Receiver<RequestJob>>,
343
386
  terminated: Arc<AtomicBool>,
344
387
  ) {
345
388
  let ruby = Ruby::get().unwrap();
346
- let server = ruby.get_inner(&ITSI_SERVER);
389
+ let mut idle_counter = 0;
390
+ let self_ref = self.clone();
347
391
  call_without_gvl(|| loop {
392
+ if receiver.is_empty() {
393
+ if let Some(oob_gc_threshold) = params.oob_gc_responses_threshold {
394
+ idle_counter = (idle_counter + 1) % oob_gc_threshold;
395
+ if idle_counter == 0 {
396
+ call_with_gvl(|_ruby| {
397
+ ruby.gc_start();
398
+ });
399
+ }
400
+ };
401
+ }
348
402
  match receiver.recv_blocking() {
349
- Ok(RequestJob::ProcessRequest(request)) => {
403
+ Ok(RequestJob::ProcessHttpRequest(request, app_proc)) => {
404
+ self_ref.request_id.fetch_add(1, Ordering::Relaxed);
405
+ self_ref.current_request_start.store(
406
+ SystemTime::now()
407
+ .duration_since(UNIX_EPOCH)
408
+ .unwrap()
409
+ .as_secs(),
410
+ Ordering::Relaxed,
411
+ );
412
+ call_with_gvl(|_ruby| {
413
+ request.process(&ruby, app_proc).ok();
414
+ });
350
415
  if terminated.load(Ordering::Relaxed) {
351
416
  break;
352
417
  }
418
+ }
419
+ Ok(RequestJob::ProcessGrpcRequest(request, app_proc)) => {
420
+ self_ref.request_id.fetch_add(1, Ordering::Relaxed);
421
+ self_ref.current_request_start.store(
422
+ SystemTime::now()
423
+ .duration_since(UNIX_EPOCH)
424
+ .unwrap()
425
+ .as_secs(),
426
+ Ordering::Relaxed,
427
+ );
353
428
  call_with_gvl(|_ruby| {
354
- request.process(&ruby, server, app).ok();
355
- })
429
+ request.process(&ruby, app_proc).ok();
430
+ });
431
+ if terminated.load(Ordering::Relaxed) {
432
+ break;
433
+ }
356
434
  }
357
435
  Ok(RequestJob::Shutdown) => {
358
- debug!("Shutting down thread worker");
359
436
  break;
360
437
  }
361
438
  Err(_) => {
@@ -63,7 +63,7 @@ pub fn configure_tls(
63
63
  .map(|s| s.to_string())
64
64
  .or_else(|| (*ITSI_ACME_CONTACT_EMAIL).as_ref().ok().map(|s| s.to_string()))
65
65
  .ok_or_else(|| itsi_error::ItsiError::ArgumentError(
66
- "acme_cert query param or ITSI_ACME_CONTACT_EMAIL must be set before you can auto-generate let's encrypt certificates".to_string(),
66
+ "acme_email query param or ITSI_ACME_CONTACT_EMAIL must be set before you can auto-generate let's encrypt certificates".to_string(),
67
67
  ))?;
68
68
 
69
69
  let acme_config = AcmeConfig::new(domains)
@@ -0,0 +1,43 @@
1
+ use std::convert::Infallible;
2
+
3
+ use bytes::Bytes;
4
+ use http::{Request, Response};
5
+ use http_body_util::combinators::BoxBody;
6
+ use hyper::body::Incoming;
7
+
8
+ pub type HttpResponse = Response<BoxBody<Bytes, Infallible>>;
9
+ pub type HttpRequest = Request<Incoming>;
10
+
11
+ pub trait RequestExt {
12
+ fn content_type(&self) -> Option<&str>;
13
+ fn accept(&self) -> Option<&str>;
14
+ fn header(&self, header_name: &str) -> Option<&str>;
15
+ fn query_param(&self, query_name: &str) -> Option<&str>;
16
+ }
17
+
18
+ impl RequestExt for HttpRequest {
19
+ fn content_type(&self) -> Option<&str> {
20
+ self.headers()
21
+ .get("content-type")
22
+ .map(|hv| hv.to_str().unwrap_or(""))
23
+ }
24
+
25
+ fn accept(&self) -> Option<&str> {
26
+ self.headers()
27
+ .get("accept")
28
+ .map(|hv| hv.to_str().unwrap_or(""))
29
+ }
30
+
31
+ fn header(&self, header_name: &str) -> Option<&str> {
32
+ self.headers()
33
+ .get(header_name)
34
+ .map(|hv| hv.to_str().unwrap_or(""))
35
+ }
36
+
37
+ fn query_param(&self, query_name: &str) -> Option<&str> {
38
+ self.uri()
39
+ .query()
40
+ .and_then(|query| query.split('&').find(|param| param.starts_with(query_name)))
41
+ .map(|param| param.split('=').nth(1).unwrap_or(""))
42
+ }
43
+ }
@@ -0,0 +1,14 @@
1
+ ---
2
+ title: Itsi Server Test Page
3
+ type: docs
4
+ prev: /
5
+ next: crates/itsi_server/src/ruby_types/readme/
6
+ ---
7
+
8
+ A simple demo page.
9
+
10
+
11
+
12
+ ## Hello World
13
+
14
+ This is a test
@@ -14,3 +14,4 @@ tracing-subscriber = { version = "0.3.19", features = [
14
14
  ] }
15
15
  tracing-attributes = "0.1"
16
16
  atty = "0.2.14"
17
+ tracing-appender = "0.2.3"