itsi 0.1.11 → 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 (293) hide show
  1. checksums.yaml +4 -4
  2. data/Cargo.lock +1535 -45
  3. data/{sandbox/itsi_itsi_file/Itsi.rb → Itsi.rb} +19 -13
  4. data/Rakefile +8 -7
  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 +34 -7
  9. data/crates/itsi_server/Cargo.toml +69 -30
  10. data/crates/itsi_server/src/lib.rs +79 -147
  11. data/crates/itsi_server/src/{body_proxy → ruby_types/itsi_body_proxy}/big_bytes.rs +10 -5
  12. data/crates/itsi_server/src/{body_proxy/itsi_body_proxy.rs → 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/{gems/server/ext/itsi_server/src/request/itsi_request.rs → crates/itsi_server/src/ruby_types/itsi_http_request.rs} +101 -117
  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 +13 -5
  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 +102 -2
  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 +38 -12
  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 +119 -42
  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 +256 -111
  61. data/crates/itsi_server/src/server/signal.rs +19 -0
  62. data/crates/itsi_server/src/server/static_file_server.rs +984 -0
  63. data/crates/itsi_server/src/server/thread_worker.rs +139 -94
  64. data/crates/itsi_server/src/server/types.rs +43 -0
  65. data/crates/itsi_server/test.md +14 -0
  66. data/crates/itsi_tracing/Cargo.toml +1 -0
  67. data/crates/itsi_tracing/src/lib.rs +216 -45
  68. data/docs/.gitignore +7 -0
  69. data/docs/.gitpod.yml +15 -0
  70. data/docs/Itsi.rb +17 -0
  71. data/docs/content/_index.md +17 -0
  72. data/docs/content/about.md +6 -0
  73. data/docs/content/docs/_index.md +18 -0
  74. data/docs/content/docs/first-page.md +9 -0
  75. data/docs/content/docs/folder/_index.md +10 -0
  76. data/docs/content/docs/folder/leaf.md +7 -0
  77. data/docs/go.mod +5 -0
  78. data/docs/go.sum +2 -0
  79. data/docs/hugo.yaml +77 -0
  80. data/examples/static_assets_example.rb +83 -0
  81. data/gems/_index.md +18 -0
  82. data/gems/scheduler/CODE_OF_CONDUCT.md +7 -0
  83. data/gems/scheduler/Cargo.lock +75 -14
  84. data/gems/scheduler/README.md +5 -0
  85. data/gems/scheduler/_index.md +7 -0
  86. data/gems/scheduler/itsi-scheduler.gemspec +4 -1
  87. data/gems/scheduler/lib/itsi/scheduler/version.rb +1 -1
  88. data/gems/scheduler/lib/itsi/scheduler.rb +2 -2
  89. data/gems/scheduler/test/test_file_io.rb +0 -1
  90. data/gems/scheduler/test/test_itsi_scheduler.rb +1 -1
  91. data/gems/server/CHANGELOG.md +5 -0
  92. data/gems/server/CODE_OF_CONDUCT.md +7 -0
  93. data/gems/server/Cargo.lock +1536 -45
  94. data/gems/server/README.md +4 -0
  95. data/gems/server/_index.md +6 -0
  96. data/gems/server/exe/itsi +33 -74
  97. data/gems/server/itsi-server.gemspec +3 -2
  98. data/gems/server/lib/itsi/{request.rb → http_request.rb} +29 -5
  99. data/gems/server/lib/itsi/http_response.rb +39 -0
  100. data/gems/server/lib/itsi/server/Itsi.rb +11 -19
  101. data/gems/server/lib/itsi/server/config/dsl.rb +506 -0
  102. data/gems/server/lib/itsi/server/config.rb +103 -8
  103. data/gems/server/lib/itsi/server/default_app/default_app.rb +38 -0
  104. data/gems/server/lib/itsi/server/grpc_interface.rb +213 -0
  105. data/gems/server/lib/itsi/server/rack/handler/itsi.rb +8 -17
  106. data/gems/server/lib/itsi/server/rack_interface.rb +23 -4
  107. data/gems/server/lib/itsi/server/scheduler_interface.rb +1 -1
  108. data/gems/server/lib/itsi/server/scheduler_mode.rb +4 -0
  109. data/gems/server/lib/itsi/server/signal_trap.rb +7 -1
  110. data/gems/server/lib/itsi/server/version.rb +1 -1
  111. data/gems/server/lib/itsi/server.rb +74 -63
  112. data/gems/server/lib/itsi/standard_headers.rb +86 -0
  113. data/gems/server/test/helpers/test_helper.rb +12 -12
  114. data/gems/server/test/test_itsi_server.rb +2 -2
  115. data/lib/itsi/version.rb +1 -1
  116. data/sandbox/itsi_file/Gemfile +11 -0
  117. data/sandbox/itsi_file/Gemfile.lock +69 -0
  118. data/sandbox/itsi_file/Itsi.rb +276 -0
  119. data/sandbox/itsi_file/error.html +2 -0
  120. data/sandbox/itsi_file/organisations_controller.rb +20 -0
  121. data/sandbox/itsi_file/public/assets/image.png +0 -0
  122. data/sandbox/itsi_file/public/assets/index.html +1 -0
  123. data/sandbox/itsi_sandbox_hanami/Gemfile.lock +2 -2
  124. data/sandbox/itsi_sandbox_rack/Gemfile.lock +2 -2
  125. data/sandbox/itsi_sandbox_rack/config.ru +2 -15
  126. data/sandbox/itsi_sandbox_rails/.dockerignore +2 -5
  127. data/sandbox/itsi_sandbox_rails/.github/workflows/ci.yml +1 -1
  128. data/sandbox/itsi_sandbox_rails/.gitignore +2 -1
  129. data/sandbox/itsi_sandbox_rails/Dockerfile +6 -9
  130. data/sandbox/itsi_sandbox_rails/Gemfile +16 -22
  131. data/sandbox/itsi_sandbox_rails/Gemfile.lock +100 -225
  132. data/sandbox/itsi_sandbox_rails/app/assets/config/manifest.js +4 -0
  133. data/sandbox/itsi_sandbox_rails/app/assets/stylesheets/application.css +11 -6
  134. data/sandbox/itsi_sandbox_rails/app/channels/application_cable/channel.rb +4 -0
  135. data/sandbox/itsi_sandbox_rails/app/channels/application_cable/connection.rb +4 -0
  136. data/sandbox/itsi_sandbox_rails/app/controllers/live_controller.rb +7 -8
  137. data/sandbox/itsi_sandbox_rails/app/controllers/uploads_controller.rb +0 -3
  138. data/sandbox/itsi_sandbox_rails/app/views/layouts/application.html.erb +2 -7
  139. data/sandbox/itsi_sandbox_rails/bin/docker-entrypoint +3 -4
  140. data/sandbox/itsi_sandbox_rails/bin/setup +8 -5
  141. data/sandbox/itsi_sandbox_rails/config/application.rb +1 -35
  142. data/sandbox/itsi_sandbox_rails/config/cable.yml +3 -10
  143. data/sandbox/itsi_sandbox_rails/config/credentials.yml.enc +1 -1
  144. data/sandbox/itsi_sandbox_rails/config/database.yml +9 -19
  145. data/sandbox/itsi_sandbox_rails/config/environment.rb +1 -1
  146. data/sandbox/itsi_sandbox_rails/config/environments/development.rb +21 -12
  147. data/sandbox/itsi_sandbox_rails/config/environments/production.rb +49 -34
  148. data/sandbox/itsi_sandbox_rails/config/environments/test.rb +19 -5
  149. data/sandbox/itsi_sandbox_rails/config/initializers/assets.rb +5 -0
  150. data/sandbox/itsi_sandbox_rails/config/initializers/filter_parameter_logging.rb +1 -1
  151. data/sandbox/itsi_sandbox_rails/config/initializers/permissions_policy.rb +13 -0
  152. data/sandbox/itsi_sandbox_rails/config/puma.rb +2 -9
  153. data/sandbox/itsi_sandbox_rails/config.ru +0 -1
  154. data/sandbox/itsi_sandbox_rails/db/migrate/20250301041554_create_posts.rb +1 -1
  155. data/sandbox/itsi_sandbox_rails/db/schema.rb +2 -2
  156. data/sandbox/itsi_sandbox_rails/lib/assets/.keep +0 -0
  157. data/sandbox/itsi_sandbox_rails/public/404.html +66 -113
  158. data/sandbox/itsi_sandbox_rails/public/406-unsupported-browser.html +65 -113
  159. data/sandbox/itsi_sandbox_rails/public/422.html +66 -113
  160. data/sandbox/itsi_sandbox_rails/public/500.html +65 -113
  161. data/sandbox/itsi_sandbox_rails/public/icon.png +0 -0
  162. data/sandbox/itsi_sandbox_rails/public/icon.svg +2 -2
  163. data/sandbox/itsi_sandbox_rails/test/channels/application_cable/connection_test.rb +13 -0
  164. data/sandbox/itsi_sandbox_roda/Gemfile.lock +3 -10
  165. data/tasks.txt +72 -35
  166. metadata +89 -139
  167. data/crates/itsi_server/src/body_proxy/mod.rs +0 -2
  168. data/crates/itsi_server/src/request/itsi_request.rs +0 -298
  169. data/crates/itsi_server/src/request/mod.rs +0 -1
  170. data/crates/itsi_server/src/response/mod.rs +0 -1
  171. data/crates/itsi_server/src/server/itsi_server.rs +0 -288
  172. data/gems/scheduler/ext/itsi_error/Cargo.lock +0 -368
  173. data/gems/scheduler/ext/itsi_error/Cargo.toml +0 -11
  174. data/gems/scheduler/ext/itsi_error/src/from.rs +0 -68
  175. data/gems/scheduler/ext/itsi_error/src/lib.rs +0 -24
  176. data/gems/scheduler/ext/itsi_instrument_entry/Cargo.toml +0 -15
  177. data/gems/scheduler/ext/itsi_instrument_entry/src/lib.rs +0 -31
  178. data/gems/scheduler/ext/itsi_rb_helpers/Cargo.lock +0 -355
  179. data/gems/scheduler/ext/itsi_rb_helpers/Cargo.toml +0 -10
  180. data/gems/scheduler/ext/itsi_rb_helpers/src/heap_value.rs +0 -121
  181. data/gems/scheduler/ext/itsi_rb_helpers/src/lib.rs +0 -201
  182. data/gems/scheduler/ext/itsi_scheduler/Cargo.toml +0 -24
  183. data/gems/scheduler/ext/itsi_scheduler/extconf.rb +0 -6
  184. data/gems/scheduler/ext/itsi_scheduler/src/itsi_scheduler/io_helpers.rs +0 -56
  185. data/gems/scheduler/ext/itsi_scheduler/src/itsi_scheduler/io_waiter.rs +0 -44
  186. data/gems/scheduler/ext/itsi_scheduler/src/itsi_scheduler/timer.rs +0 -44
  187. data/gems/scheduler/ext/itsi_scheduler/src/itsi_scheduler.rs +0 -308
  188. data/gems/scheduler/ext/itsi_scheduler/src/lib.rs +0 -38
  189. data/gems/scheduler/ext/itsi_server/Cargo.lock +0 -2956
  190. data/gems/scheduler/ext/itsi_server/Cargo.toml +0 -50
  191. data/gems/scheduler/ext/itsi_server/extconf.rb +0 -6
  192. data/gems/scheduler/ext/itsi_server/src/body_proxy/big_bytes.rs +0 -104
  193. data/gems/scheduler/ext/itsi_server/src/body_proxy/itsi_body_proxy.rs +0 -122
  194. data/gems/scheduler/ext/itsi_server/src/body_proxy/mod.rs +0 -2
  195. data/gems/scheduler/ext/itsi_server/src/env.rs +0 -43
  196. data/gems/scheduler/ext/itsi_server/src/lib.rs +0 -180
  197. data/gems/scheduler/ext/itsi_server/src/request/itsi_request.rs +0 -298
  198. data/gems/scheduler/ext/itsi_server/src/request/mod.rs +0 -1
  199. data/gems/scheduler/ext/itsi_server/src/response/itsi_response.rs +0 -357
  200. data/gems/scheduler/ext/itsi_server/src/response/mod.rs +0 -1
  201. data/gems/scheduler/ext/itsi_server/src/server/bind.rs +0 -174
  202. data/gems/scheduler/ext/itsi_server/src/server/bind_protocol.rs +0 -37
  203. data/gems/scheduler/ext/itsi_server/src/server/io_stream.rs +0 -104
  204. data/gems/scheduler/ext/itsi_server/src/server/itsi_server.rs +0 -288
  205. data/gems/scheduler/ext/itsi_server/src/server/lifecycle_event.rs +0 -9
  206. data/gems/scheduler/ext/itsi_server/src/server/listener.rs +0 -318
  207. data/gems/scheduler/ext/itsi_server/src/server/mod.rs +0 -11
  208. data/gems/scheduler/ext/itsi_server/src/server/process_worker.rs +0 -203
  209. data/gems/scheduler/ext/itsi_server/src/server/serve_strategy/cluster_mode.rs +0 -260
  210. data/gems/scheduler/ext/itsi_server/src/server/serve_strategy/mod.rs +0 -27
  211. data/gems/scheduler/ext/itsi_server/src/server/serve_strategy/single_mode.rs +0 -276
  212. data/gems/scheduler/ext/itsi_server/src/server/signal.rs +0 -74
  213. data/gems/scheduler/ext/itsi_server/src/server/thread_worker.rs +0 -399
  214. data/gems/scheduler/ext/itsi_server/src/server/tls/locked_dir_cache.rs +0 -132
  215. data/gems/scheduler/ext/itsi_server/src/server/tls.rs +0 -265
  216. data/gems/scheduler/ext/itsi_tracing/Cargo.lock +0 -274
  217. data/gems/scheduler/ext/itsi_tracing/Cargo.toml +0 -16
  218. data/gems/scheduler/ext/itsi_tracing/src/lib.rs +0 -58
  219. data/gems/server/ext/itsi_error/Cargo.lock +0 -368
  220. data/gems/server/ext/itsi_error/Cargo.toml +0 -11
  221. data/gems/server/ext/itsi_error/src/from.rs +0 -68
  222. data/gems/server/ext/itsi_error/src/lib.rs +0 -24
  223. data/gems/server/ext/itsi_instrument_entry/Cargo.toml +0 -15
  224. data/gems/server/ext/itsi_instrument_entry/src/lib.rs +0 -31
  225. data/gems/server/ext/itsi_rb_helpers/Cargo.lock +0 -355
  226. data/gems/server/ext/itsi_rb_helpers/Cargo.toml +0 -10
  227. data/gems/server/ext/itsi_rb_helpers/src/heap_value.rs +0 -121
  228. data/gems/server/ext/itsi_rb_helpers/src/lib.rs +0 -201
  229. data/gems/server/ext/itsi_scheduler/Cargo.toml +0 -24
  230. data/gems/server/ext/itsi_scheduler/extconf.rb +0 -6
  231. data/gems/server/ext/itsi_scheduler/src/itsi_scheduler/io_helpers.rs +0 -56
  232. data/gems/server/ext/itsi_scheduler/src/itsi_scheduler/io_waiter.rs +0 -44
  233. data/gems/server/ext/itsi_scheduler/src/itsi_scheduler/timer.rs +0 -44
  234. data/gems/server/ext/itsi_scheduler/src/itsi_scheduler.rs +0 -308
  235. data/gems/server/ext/itsi_scheduler/src/lib.rs +0 -38
  236. data/gems/server/ext/itsi_server/Cargo.lock +0 -2956
  237. data/gems/server/ext/itsi_server/Cargo.toml +0 -50
  238. data/gems/server/ext/itsi_server/extconf.rb +0 -6
  239. data/gems/server/ext/itsi_server/src/body_proxy/big_bytes.rs +0 -104
  240. data/gems/server/ext/itsi_server/src/body_proxy/itsi_body_proxy.rs +0 -122
  241. data/gems/server/ext/itsi_server/src/body_proxy/mod.rs +0 -2
  242. data/gems/server/ext/itsi_server/src/env.rs +0 -43
  243. data/gems/server/ext/itsi_server/src/lib.rs +0 -180
  244. data/gems/server/ext/itsi_server/src/request/mod.rs +0 -1
  245. data/gems/server/ext/itsi_server/src/response/itsi_response.rs +0 -357
  246. data/gems/server/ext/itsi_server/src/response/mod.rs +0 -1
  247. data/gems/server/ext/itsi_server/src/server/bind.rs +0 -174
  248. data/gems/server/ext/itsi_server/src/server/bind_protocol.rs +0 -37
  249. data/gems/server/ext/itsi_server/src/server/io_stream.rs +0 -104
  250. data/gems/server/ext/itsi_server/src/server/itsi_server.rs +0 -288
  251. data/gems/server/ext/itsi_server/src/server/lifecycle_event.rs +0 -9
  252. data/gems/server/ext/itsi_server/src/server/listener.rs +0 -318
  253. data/gems/server/ext/itsi_server/src/server/mod.rs +0 -11
  254. data/gems/server/ext/itsi_server/src/server/process_worker.rs +0 -203
  255. data/gems/server/ext/itsi_server/src/server/serve_strategy/cluster_mode.rs +0 -260
  256. data/gems/server/ext/itsi_server/src/server/serve_strategy/mod.rs +0 -27
  257. data/gems/server/ext/itsi_server/src/server/serve_strategy/single_mode.rs +0 -276
  258. data/gems/server/ext/itsi_server/src/server/signal.rs +0 -74
  259. data/gems/server/ext/itsi_server/src/server/thread_worker.rs +0 -399
  260. data/gems/server/ext/itsi_server/src/server/tls/locked_dir_cache.rs +0 -132
  261. data/gems/server/ext/itsi_server/src/server/tls.rs +0 -265
  262. data/gems/server/ext/itsi_tracing/Cargo.lock +0 -274
  263. data/gems/server/ext/itsi_tracing/Cargo.toml +0 -16
  264. data/gems/server/ext/itsi_tracing/src/lib.rs +0 -58
  265. data/gems/server/lib/itsi/server/options_dsl.rb +0 -401
  266. data/gems/server/lib/itsi/stream_io.rb +0 -38
  267. data/location_dsl.rb +0 -381
  268. data/sandbox/itsi_sandbox_rails/.kamal/hooks/docker-setup.sample +0 -3
  269. data/sandbox/itsi_sandbox_rails/.kamal/hooks/post-app-boot.sample +0 -3
  270. data/sandbox/itsi_sandbox_rails/.kamal/hooks/post-deploy.sample +0 -14
  271. data/sandbox/itsi_sandbox_rails/.kamal/hooks/post-proxy-reboot.sample +0 -3
  272. data/sandbox/itsi_sandbox_rails/.kamal/hooks/pre-app-boot.sample +0 -3
  273. data/sandbox/itsi_sandbox_rails/.kamal/hooks/pre-build.sample +0 -51
  274. data/sandbox/itsi_sandbox_rails/.kamal/hooks/pre-connect.sample +0 -47
  275. data/sandbox/itsi_sandbox_rails/.kamal/hooks/pre-deploy.sample +0 -109
  276. data/sandbox/itsi_sandbox_rails/.kamal/hooks/pre-proxy-reboot.sample +0 -3
  277. data/sandbox/itsi_sandbox_rails/.kamal/secrets +0 -17
  278. data/sandbox/itsi_sandbox_rails/bin/dev +0 -2
  279. data/sandbox/itsi_sandbox_rails/bin/jobs +0 -6
  280. data/sandbox/itsi_sandbox_rails/bin/kamal +0 -27
  281. data/sandbox/itsi_sandbox_rails/bin/thrust +0 -5
  282. data/sandbox/itsi_sandbox_rails/config/cache.yml +0 -16
  283. data/sandbox/itsi_sandbox_rails/config/deploy.yml +0 -116
  284. data/sandbox/itsi_sandbox_rails/config/queue.yml +0 -18
  285. data/sandbox/itsi_sandbox_rails/config/recurring.yml +0 -10
  286. data/sandbox/itsi_sandbox_rails/db/cable_schema.rb +0 -11
  287. data/sandbox/itsi_sandbox_rails/db/cache_schema.rb +0 -14
  288. data/sandbox/itsi_sandbox_rails/db/queue_schema.rb +0 -129
  289. data/sandbox/itsi_sandbox_rails/public/400.html +0 -114
  290. data/sandbox/itsi_sandbox_rails/test/fixtures/posts.yml +0 -9
  291. data/sandbox/itsi_sandbox_rails/test/models/post_test.rb +0 -7
  292. /data/{sandbox/itsi_sandbox_rails/script/.keep → crates/_index.md} +0 -0
  293. /data/gems/server/lib/itsi/{index.html → server/default_app/index.html} +0 -0
@@ -1,9 +1,8 @@
1
- use super::itsi_server::{RequestJob, Server};
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,26 +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 server: Arc<Server>,
28
- pub id: String,
29
- 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,
30
38
  pub receiver: Arc<async_channel::Receiver<RequestJob>>,
31
- pub sender: async_channel::Sender<RequestJob>,
39
+ pub sender: Sender<RequestJob>,
32
40
  pub thread: RwLock<Option<HeapValue<Thread>>>,
33
41
  pub terminated: Arc<AtomicBool>,
34
42
  pub scheduler_class: Option<Opaque<Value>>,
35
43
  }
36
44
 
37
- static ID_CALL: LazyId = LazyId::new("call");
38
45
  static ID_ALIVE: LazyId = LazyId::new("alive?");
39
46
  static ID_SCHEDULER: LazyId = LazyId::new("scheduler");
40
47
  static ID_SCHEDULE: LazyId = LazyId::new("schedule");
@@ -48,28 +55,26 @@ static CLASS_FIBER: Lazy<RClass> = Lazy::new(|ruby| {
48
55
  });
49
56
 
50
57
  pub struct TerminateWakerSignal(bool);
58
+ type ThreadWorkerBuildResult = Result<(Arc<Vec<Arc<ThreadWorker>>>, Sender<RequestJob>)>;
51
59
 
52
- #[instrument(name = "Boot", parent=None, skip(server, threads, app, pid, scheduler_class))]
60
+ #[instrument(name = "boot", parent=None, skip(params, threads, pid))]
53
61
  pub fn build_thread_workers(
54
- server: Arc<Server>,
62
+ params: Arc<ServerParams>,
55
63
  pid: Pid,
56
64
  threads: NonZeroU8,
57
- app: HeapVal,
58
- scheduler_class: Option<String>,
59
- ) -> Result<(Arc<Vec<ThreadWorker>>, async_channel::Sender<RequestJob>)> {
60
- let (sender, receiver) = async_channel::bounded(20);
65
+ ) -> ThreadWorkerBuildResult {
66
+ let (sender, receiver) = async_channel::bounded((threads.get() as u16 * 30) as usize);
61
67
  let receiver_ref = Arc::new(receiver);
62
68
  let sender_ref = sender;
63
- let (app, scheduler_class) = load_app(app, scheduler_class)?;
69
+ let scheduler_class = load_scheduler_class(params.scheduler_class.clone())?;
64
70
  Ok((
65
71
  Arc::new(
66
72
  (1..=u8::from(threads))
67
73
  .map(|id| {
68
- info!(pid = pid.as_raw(), id, "Thread");
69
74
  ThreadWorker::new(
70
- server.clone(),
75
+ params.clone(),
76
+ id,
71
77
  format!("{:?}#{:?}", pid, id),
72
- app,
73
78
  receiver_ref.clone(),
74
79
  sender_ref.clone(),
75
80
  scheduler_class,
@@ -81,12 +86,8 @@ pub fn build_thread_workers(
81
86
  ))
82
87
  }
83
88
 
84
- pub fn load_app(
85
- app: HeapVal,
86
- scheduler_class: Option<String>,
87
- ) -> Result<(Opaque<Value>, Option<Opaque<Value>>)> {
89
+ pub fn load_scheduler_class(scheduler_class: Option<String>) -> Result<Option<Opaque<Value>>> {
88
90
  call_with_gvl(|ruby| {
89
- let app = Opaque::from(app.funcall::<_, _, Value>(*ID_CALL, ())?);
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,67 @@ 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
- server: Arc<Server>,
104
- id: String,
105
- app: Opaque<Value>,
104
+ params: Arc<ServerParams>,
105
+ id: u8,
106
+ name: String,
106
107
  receiver: Arc<async_channel::Receiver<RequestJob>>,
107
- sender: async_channel::Sender<RequestJob>,
108
+ sender: Sender<RequestJob>,
108
109
  scheduler_class: Option<Opaque<Value>>,
109
- ) -> Result<Self> {
110
- let mut worker = Self {
111
- server,
110
+ ) -> Result<Arc<Self>> {
111
+ let worker = Arc::new(Self {
112
+ params,
112
113
  id,
113
- app,
114
+ request_id: AtomicU64::new(0),
115
+ current_request_start: AtomicU64::new(0),
116
+ name,
114
117
  receiver,
115
118
  sender,
116
119
  thread: RwLock::new(None),
117
120
  terminated: Arc::new(AtomicBool::new(false)),
118
121
  scheduler_class,
119
- };
120
- worker.run()?;
122
+ });
123
+ worker.clone().run()?;
121
124
  Ok(worker)
122
125
  }
123
126
 
124
- #[instrument(skip(self), fields(id = self.id))]
125
- pub async fn request_shutdown(&self) {
126
- match self.sender.send(RequestJob::Shutdown).await {
127
- Ok(_) => {}
128
- Err(err) => error!("Failed to send shutdown request: {}", err),
129
- };
130
- debug!("Requesting shutdown");
131
- }
132
-
133
127
  #[instrument(skip(self, deadline), fields(id = self.id))]
134
128
  pub fn poll_shutdown(&self, deadline: Instant) -> bool {
135
- call_with_gvl(|_ruby| {
136
- if let Some(thread) = self.thread.read().deref() {
137
- if Instant::now() > deadline {
138
- warn!("Worker shutdown timed out. Killing thread");
139
- self.terminated.store(true, Ordering::SeqCst);
140
- kill_threads(vec![thread.as_value()]);
141
- }
142
- if thread.funcall::<_, _, bool>(*ID_ALIVE, ()).unwrap_or(false) {
143
- return true;
144
- }
145
- debug!("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()]);
146
134
  }
147
- 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();
148
142
 
149
- false
150
- })
143
+ false
151
144
  }
152
145
 
153
- pub fn run(&mut self) -> Result<()> {
154
- let id = self.id.clone();
155
- let app = self.app;
146
+ pub fn run(self: Arc<Self>) -> Result<()> {
147
+ let name = self.name.clone();
156
148
  let receiver = self.receiver.clone();
157
149
  let terminated = self.terminated.clone();
158
150
  let scheduler_class = self.scheduler_class;
159
- let server = self.server.clone();
151
+ let params = self.params.clone();
152
+ let self_ref = self.clone();
160
153
  call_with_gvl(|_| {
161
154
  *self.thread.write() = Some(
162
155
  create_ruby_thread(move || {
163
156
  if let Some(scheduler_class) = scheduler_class {
164
- if let Err(err) = Self::fiber_accept_loop(
165
- server,
166
- id,
167
- app,
157
+ if let Err(err) = self_ref.fiber_accept_loop(
158
+ params,
159
+ name,
168
160
  receiver,
169
161
  scheduler_class,
170
162
  terminated,
@@ -172,7 +164,7 @@ impl ThreadWorker {
172
164
  error!("Error in fiber_accept_loop: {:?}", err);
173
165
  }
174
166
  } else {
175
- Self::accept_loop(server, id, app, receiver, terminated);
167
+ self_ref.accept_loop(params, name, receiver, terminated);
176
168
  }
177
169
  })
178
170
  .into(),
@@ -183,7 +175,7 @@ impl ThreadWorker {
183
175
  }
184
176
 
185
177
  pub fn build_scheduler_proc(
186
- app: Opaque<Value>,
178
+ self: Arc<Self>,
187
179
  leader: &Arc<Mutex<Option<RequestJob>>>,
188
180
  receiver: &Arc<async_channel::Receiver<RequestJob>>,
189
181
  terminated: &Arc<AtomicBool>,
@@ -205,6 +197,7 @@ impl ThreadWorker {
205
197
  let receiver = receiver.clone();
206
198
  let terminated = terminated.clone();
207
199
  let waker_sender = waker_sender.clone();
200
+ let self_ref = self.clone();
208
201
  let mut batch = Vec::with_capacity(MAX_BATCH_SIZE as usize);
209
202
 
210
203
  static MAX_BATCH_SIZE: i32 = 25;
@@ -212,8 +205,11 @@ impl ThreadWorker {
212
205
  let mut idle_counter = 0;
213
206
  if let Some(v) = leader_clone.lock().take() {
214
207
  match v {
215
- RequestJob::ProcessRequest(itsi_request) => {
216
- 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))
217
213
  }
218
214
  RequestJob::Shutdown => {
219
215
  waker_sender.send(TerminateWakerSignal(true)).unwrap();
@@ -232,12 +228,38 @@ impl ThreadWorker {
232
228
  let shutdown_requested = call_with_gvl(|_| {
233
229
  for req in batch.drain(..) {
234
230
  match req {
235
- 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
+ );
236
240
  let response = request.response.clone();
237
- if let Err(err) =
238
- server.funcall::<_, _, Value>(*ID_SCHEDULE, (app, request))
239
- {
240
- 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)
241
263
  }
242
264
  }
243
265
  RequestJob::Shutdown => return true,
@@ -276,12 +298,11 @@ impl ThreadWorker {
276
298
  })
277
299
  }
278
300
 
279
- #[instrument(skip_all, fields(thread_worker=id))]
301
+ #[instrument(skip_all, fields(thread_worker=name))]
280
302
  pub fn fiber_accept_loop(
281
- server: Arc<Server>,
282
-
283
- id: String,
284
- app: Opaque<Value>,
303
+ self: Arc<Self>,
304
+ params: Arc<ServerParams>,
305
+ name: String,
285
306
  receiver: Arc<async_channel::Receiver<RequestJob>>,
286
307
  scheduler_class: Opaque<Value>,
287
308
  terminated: Arc<AtomicBool>,
@@ -290,13 +311,12 @@ impl ThreadWorker {
290
311
  let (waker_sender, waker_receiver) = watch::channel(TerminateWakerSignal(false));
291
312
  let leader: Arc<Mutex<Option<RequestJob>>> = Arc::new(Mutex::new(None));
292
313
  let server_class = ruby.get_inner(&ITSI_SERVER);
293
- let scheduler_proc = Self::build_scheduler_proc(
294
- app,
314
+ let scheduler_proc = self.build_scheduler_proc(
295
315
  &leader,
296
316
  &receiver,
297
317
  &terminated,
298
318
  &waker_sender,
299
- server.oob_gc_responses_threshold,
319
+ params.oob_gc_responses_threshold,
300
320
  );
301
321
  let (scheduler, scheduler_fiber) = server_class.funcall::<_, _, (Value, Value)>(
302
322
  "start_scheduler_loop",
@@ -359,35 +379,60 @@ impl ThreadWorker {
359
379
 
360
380
  #[instrument(skip_all, fields(thread_worker=id))]
361
381
  pub fn accept_loop(
362
- server: Arc<Server>,
382
+ self: Arc<Self>,
383
+ params: Arc<ServerParams>,
363
384
  id: String,
364
- app: Opaque<Value>,
365
385
  receiver: Arc<async_channel::Receiver<RequestJob>>,
366
386
  terminated: Arc<AtomicBool>,
367
387
  ) {
368
388
  let ruby = Ruby::get().unwrap();
369
- let server_class = ruby.get_inner(&ITSI_SERVER);
370
389
  let mut idle_counter = 0;
390
+ let self_ref = self.clone();
371
391
  call_without_gvl(|| loop {
372
392
  if receiver.is_empty() {
373
- if let Some(oob_gc_threshold) = server.oob_gc_responses_threshold {
393
+ if let Some(oob_gc_threshold) = params.oob_gc_responses_threshold {
374
394
  idle_counter = (idle_counter + 1) % oob_gc_threshold;
375
395
  if idle_counter == 0 {
376
- ruby.gc_start();
396
+ call_with_gvl(|_ruby| {
397
+ ruby.gc_start();
398
+ });
377
399
  }
378
400
  };
379
401
  }
380
402
  match receiver.recv_blocking() {
381
- 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
+ });
382
415
  if terminated.load(Ordering::Relaxed) {
383
416
  break;
384
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
+ );
385
428
  call_with_gvl(|_ruby| {
386
- request.process(&ruby, server_class, app).ok();
387
- })
429
+ request.process(&ruby, app_proc).ok();
430
+ });
431
+ if terminated.load(Ordering::Relaxed) {
432
+ break;
433
+ }
388
434
  }
389
435
  Ok(RequestJob::Shutdown) => {
390
- debug!("Shutting down thread worker");
391
436
  break;
392
437
  }
393
438
  Err(_) => {
@@ -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"