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,24 +0,0 @@
1
- [package]
2
- name = "itsi-scheduler"
3
- version = "0.1.0"
4
- edition = "2021"
5
- authors = ["Wouter Coppieters <wc@pico.net.nz>"]
6
- license = "MIT"
7
- publish = false
8
-
9
- [lib]
10
- crate-type = ["cdylib"]
11
-
12
- [dependencies]
13
- magnus = { version = "0.7.1", features = ["rb-sys", "bytes"] }
14
- derive_more = { version = "2.0.1", features = ["debug"] }
15
- itsi_tracing = { path = "../itsi_tracing" }
16
- itsi_rb_helpers = { path = "../itsi_rb_helpers" }
17
- itsi_error = { path = "../itsi_error" }
18
- itsi_instrument_entry = { path = "../itsi_instrument_entry" }
19
- parking_lot = "0.12.3"
20
- mio = { version = "1.0.3", features = ["os-poll", "os-ext"] }
21
- rb-sys = "0.9.105"
22
- bytes = "1.10.1"
23
- nix = "0.29.0"
24
- tracing = "0.1.41"
@@ -1,6 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "mkmf"
4
- require "rb_sys/mkmf"
5
-
6
- create_rust_makefile("itsi/scheduler/itsi_scheduler")
@@ -1,56 +0,0 @@
1
- use std::os::fd::RawFd;
2
-
3
- use itsi_error::{ItsiError, Result};
4
- use mio::Interest;
5
- use nix::libc::{fcntl, poll, pollfd, F_GETFL, F_SETFL, O_NONBLOCK};
6
-
7
- use super::Readiness;
8
-
9
- pub fn set_nonblocking(fd: RawFd) -> itsi_error::Result<()> {
10
- unsafe {
11
- let flags = fcntl(fd, F_GETFL);
12
- if flags < 0 {
13
- return Err(ItsiError::ArgumentError(format!(
14
- "fcntl(F_GETFL) error for fd {}: {}",
15
- fd,
16
- std::io::Error::last_os_error()
17
- )));
18
- }
19
- let new_flags = flags | O_NONBLOCK;
20
- if fcntl(fd, F_SETFL, new_flags) < 0 {
21
- return Err(ItsiError::ArgumentError(format!(
22
- "fcntl(F_SETFL) error for fd {}: {}",
23
- fd,
24
- std::io::Error::last_os_error()
25
- )));
26
- }
27
- }
28
- Ok(())
29
- }
30
-
31
- pub fn poll_readiness(fd: RawFd, events: i16) -> Option<Readiness> {
32
- let mut pfd = pollfd {
33
- fd,
34
- events,
35
- revents: 0,
36
- };
37
- let ret = unsafe { poll(&mut pfd as *mut pollfd, 1, 0) };
38
- if ret > 0 {
39
- return Some(Readiness(pfd.revents));
40
- }
41
- None
42
- }
43
-
44
- pub fn build_interest(events: i16) -> Result<Interest> {
45
- let mut interest_opt = None;
46
- if events & 1 != 0 {
47
- interest_opt = Some(Interest::READABLE);
48
- }
49
- if events & 4 != 0 {
50
- interest_opt = Some(match interest_opt {
51
- Some(i) => i | Interest::WRITABLE,
52
- None => Interest::WRITABLE,
53
- });
54
- }
55
- interest_opt.ok_or_else(|| ItsiError::ArgumentError("No valid event specified".to_owned()))
56
- }
@@ -1,44 +0,0 @@
1
- use derive_more::Debug;
2
- use mio::{event::Source, unix::SourceFd, Interest, Token};
3
- use std::os::fd::RawFd;
4
-
5
- #[derive(Debug, Clone, PartialEq, Eq, Hash)]
6
- pub struct IoWaiter {
7
- pub fd: RawFd,
8
- pub readiness: i16,
9
- pub token: Token,
10
- }
11
-
12
- impl IoWaiter {
13
- pub fn new(fd: RawFd, readiness: i16, token: Token) -> Self {
14
- Self {
15
- fd,
16
- readiness,
17
- token,
18
- }
19
- }
20
- }
21
-
22
- impl Source for IoWaiter {
23
- fn register(
24
- &mut self,
25
- registry: &mio::Registry,
26
- token: Token,
27
- interests: Interest,
28
- ) -> std::io::Result<()> {
29
- SourceFd(&self.fd).register(registry, token, interests)
30
- }
31
-
32
- fn reregister(
33
- &mut self,
34
- registry: &mio::Registry,
35
- token: Token,
36
- interests: Interest,
37
- ) -> std::io::Result<()> {
38
- SourceFd(&self.fd).reregister(registry, token, interests)
39
- }
40
-
41
- fn deregister(&mut self, registry: &mio::Registry) -> std::io::Result<()> {
42
- SourceFd(&self.fd).deregister(registry)
43
- }
44
- }
@@ -1,44 +0,0 @@
1
- use std::{
2
- cmp::Ordering,
3
- time::{Duration, Instant},
4
- };
5
-
6
- use mio::Token;
7
-
8
- #[derive(Debug, Clone, PartialEq, Eq)]
9
- pub struct Timer {
10
- pub wake_time: Instant,
11
- pub token: Token,
12
- }
13
- impl PartialOrd for Timer {
14
- fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
15
- Some(self.cmp(other))
16
- }
17
- }
18
-
19
- impl Ord for Timer {
20
- fn cmp(&self, other: &Self) -> Ordering {
21
- // Reverse the order: a timer with an earlier wake_time should be considered greater.
22
- other
23
- .wake_time
24
- .cmp(&self.wake_time)
25
- .then_with(|| other.token.cmp(&self.token))
26
- }
27
- }
28
-
29
- impl Timer {
30
- pub fn new(wake_in: Duration, token: Token) -> Self {
31
- Self {
32
- wake_time: Instant::now() + wake_in,
33
- token,
34
- }
35
- }
36
-
37
- pub fn is_due(&self) -> bool {
38
- self.wake_time <= Instant::now()
39
- }
40
-
41
- pub(crate) fn duration(&self) -> Option<Duration> {
42
- self.wake_time.checked_duration_since(Instant::now())
43
- }
44
- }
@@ -1,308 +0,0 @@
1
- mod io_helpers;
2
- mod io_waiter;
3
- mod timer;
4
- use io_helpers::{build_interest, poll_readiness, set_nonblocking};
5
- use io_waiter::IoWaiter;
6
- use itsi_error::ItsiError;
7
- use itsi_rb_helpers::{call_without_gvl, create_ruby_thread};
8
- use magnus::{
9
- error::Result as MagnusResult,
10
- value::{InnerValue, Opaque, ReprValue},
11
- Module, RClass, Ruby, Value,
12
- };
13
- use mio::{Events, Poll, Token, Waker};
14
- use parking_lot::{Mutex, RwLock};
15
- use std::{
16
- collections::{BinaryHeap, HashMap, VecDeque},
17
- os::fd::RawFd,
18
- sync::Arc,
19
- time::Duration,
20
- };
21
- use timer::Timer;
22
- use tracing::{debug, info, warn};
23
-
24
- #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
25
- pub(crate) struct Readiness(i16);
26
-
27
- impl std::fmt::Debug for ItsiScheduler {
28
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
29
- f.debug_struct("ItsiScheduler").finish()
30
- }
31
- }
32
-
33
- const WAKE_TOKEN: Token = Token(0);
34
-
35
- #[magnus::wrap(class = "Itsi::Scheduler", free_immediately, size)]
36
- pub(crate) struct ItsiScheduler {
37
- timers: Mutex<BinaryHeap<Timer>>,
38
- io_waiters: Mutex<HashMap<Token, IoWaiter>>,
39
- registry: Mutex<HashMap<RawFd, VecDeque<IoWaiter>>>,
40
- poll: Mutex<Poll>,
41
- events: Mutex<Events>,
42
- waker: Mutex<Waker>,
43
- }
44
-
45
- impl Default for ItsiScheduler {
46
- fn default() -> Self {
47
- let poll = Poll::new().unwrap();
48
- let waker = Waker::new(poll.registry(), WAKE_TOKEN).unwrap();
49
- let events = Events::with_capacity(1024);
50
-
51
- ItsiScheduler {
52
- timers: Mutex::new(BinaryHeap::new()),
53
- io_waiters: Mutex::new(HashMap::new()),
54
- registry: Mutex::new(HashMap::new()),
55
- poll: Mutex::new(poll),
56
- events: Mutex::new(events),
57
- waker: Mutex::new(waker),
58
- }
59
- }
60
- }
61
-
62
- impl ItsiScheduler {
63
- pub fn initialize(&self) {}
64
-
65
- pub fn wake(&self) -> MagnusResult<()> {
66
- self.waker.lock().wake().map_err(|_| {
67
- magnus::Error::new(
68
- magnus::exception::exception(),
69
- "Failed to wake the scheduler",
70
- )
71
- })?;
72
- Ok(())
73
- }
74
- pub fn register_io_wait(
75
- &self,
76
- io_obj: i32,
77
- events: i16,
78
- timeout: Option<f64>,
79
- token: usize,
80
- ) -> MagnusResult<Option<i16>> {
81
- debug!(
82
- "Registering IO Wait for {:?}, {:?}, {:?}, {:?}",
83
- io_obj, events, timeout, token
84
- );
85
- let fd: RawFd = io_obj;
86
-
87
- let readiness = poll_readiness(fd, events).unwrap_or(Readiness(0));
88
- if readiness == Readiness(events) {
89
- return Ok(Some(readiness.0));
90
- }
91
-
92
- set_nonblocking(fd)?;
93
- let interest = build_interest(events)?;
94
- let token = Token(token);
95
- let mut waiter = IoWaiter::new(fd, events, token);
96
- self.io_waiters.lock().insert(token, waiter.clone());
97
- let mut binding = self.registry.lock();
98
- let queue = binding.entry(fd).or_default();
99
-
100
- queue.push_back(waiter.clone());
101
-
102
- if queue.len() == 1 {
103
- self.poll
104
- .lock()
105
- .registry()
106
- .register(&mut waiter, token, interest)
107
- .map_err(|e| ItsiError::ArgumentError(format!("register error: {}", e)))?;
108
- }
109
- Ok(None)
110
- }
111
-
112
- pub fn start_timer(&self, timeout: Option<f64>, token: usize) {
113
- if timeout.is_some_and(|t| t >= 0.0) {
114
- let timer_entry = Timer::new(Duration::from_secs_f64(timeout.unwrap()), Token(token));
115
- self.timers.lock().push(timer_entry);
116
- }
117
- }
118
- pub fn has_pending_io(&self) -> bool {
119
- !self.timers.lock().is_empty() || !self.io_waiters.lock().is_empty()
120
- }
121
-
122
- pub fn class_info(msg: String) {
123
- info!(msg);
124
- }
125
-
126
- pub fn info(&self, msg: String) {
127
- info!(msg);
128
- }
129
-
130
- pub fn warn(&self, msg: String) {
131
- warn!(msg);
132
- }
133
-
134
- pub fn debug(&self, msg: String) {
135
- debug!(msg);
136
- }
137
-
138
- pub fn fetch_due_events(&self) -> MagnusResult<Option<Vec<(usize, i16)>>> {
139
- call_without_gvl(|| {
140
- let timeout = if let Some(timer) = self.timers.lock().peek() {
141
- timer.duration().or(Some(Duration::ZERO))
142
- } else {
143
- None
144
- };
145
- let mut due_fibers: Option<Vec<(usize, i16)>> = None;
146
- let mut io_waiters = self.io_waiters.lock();
147
- if !io_waiters.is_empty() || timeout.is_none() {
148
- let mut events = self.events.lock();
149
- {
150
- let mut poll = self.poll.lock();
151
- poll.poll(&mut events, timeout)
152
- .map_err(|e| ItsiError::ArgumentError(format!("poll error: {}", e)))?;
153
- };
154
-
155
- for event in events.iter() {
156
- let token = event.token();
157
- if token == WAKE_TOKEN {
158
- continue;
159
- }
160
-
161
- let waiter = io_waiters.remove(&token);
162
- if waiter.is_none() {
163
- continue;
164
- }
165
- let mut waiter = waiter.unwrap();
166
- let mut evt_readiness = 0;
167
- if event.is_readable() {
168
- evt_readiness |= 1;
169
- }
170
- if event.is_priority() {
171
- evt_readiness |= 2;
172
- }
173
- if event.is_writable() {
174
- evt_readiness |= 4
175
- }
176
- self.poll
177
- .lock()
178
- .registry()
179
- .deregister(&mut waiter)
180
- .map_err(|_| {
181
- ItsiError::ArgumentError("Failed to deregister".to_string())
182
- })?;
183
-
184
- due_fibers
185
- .get_or_insert_default()
186
- .push((waiter.token.0, evt_readiness));
187
-
188
- let mut binding = self.registry.lock();
189
- // Pop the current item for the current waiter off the queue
190
- let queue = binding.get_mut(&(waiter.fd)).unwrap();
191
- queue.pop_front();
192
-
193
- if let Some(head) = queue.get_mut(0) {
194
- // Register the next item in the queue if there is one.
195
- let interest = build_interest(head.readiness)?;
196
- self.poll
197
- .lock()
198
- .registry()
199
- .register(head, head.token, interest)
200
- .map_err(|_| {
201
- ItsiError::ArgumentError("Failed to deregister".to_string())
202
- })?;
203
- } else {
204
- // Otherwise we drop the queue altogether.
205
- binding.remove(&waiter.fd);
206
- }
207
- }
208
- return Ok(due_fibers);
209
- }
210
- Ok(None)
211
- })
212
- }
213
-
214
- pub fn run_blocking_in_thread<T, F>(&self, ruby: &Ruby, work: F) -> MagnusResult<Option<T>>
215
- where
216
- T: Send + Sync + std::fmt::Debug + 'static,
217
- F: FnOnce() -> Option<T> + Send + 'static,
218
- {
219
- let result: Arc<RwLock<Option<T>>> = Arc::new(RwLock::new(None));
220
- let result_clone = Arc::clone(&result);
221
-
222
- let current_fiber = Opaque::from(ruby.fiber_current());
223
- let scheduler = Opaque::from(
224
- ruby.module_kernel()
225
- .const_get::<_, RClass>("Fiber")
226
- .unwrap()
227
- .funcall::<_, _, Value>("scheduler", ())
228
- .unwrap(),
229
- );
230
-
231
- create_ruby_thread(move || {
232
- call_without_gvl(|| {
233
- let outcome = work();
234
- *result_clone.write() = outcome;
235
- });
236
-
237
- let ruby = Ruby::get().unwrap();
238
- scheduler
239
- .get_inner_with(&ruby)
240
- .funcall::<_, _, Value>("unblock", (None::<String>, current_fiber))
241
- .unwrap();
242
- });
243
-
244
- scheduler
245
- .get_inner_with(ruby)
246
- .funcall::<_, _, Value>("block", (None::<Value>, None::<u64>))?;
247
-
248
- let result_opt = Arc::try_unwrap(result).unwrap().write().take();
249
- Ok(result_opt)
250
- }
251
-
252
- pub fn address_resolve(
253
- ruby: &Ruby,
254
- rself: &Self,
255
- hostname: String,
256
- ) -> MagnusResult<Option<Vec<String>>> {
257
- let result: Option<Vec<String>> = rself.run_blocking_in_thread(ruby, move || {
258
- use std::net::ToSocketAddrs;
259
- let addrs_res = (hostname.as_str(), 0).to_socket_addrs();
260
- match addrs_res {
261
- Ok(addrs) => {
262
- let ips: Vec<String> = addrs.map(|s| s.ip().to_string()).collect();
263
- Some(ips)
264
- }
265
- Err(_) => None,
266
- }
267
- })?;
268
- Ok(result)
269
- }
270
-
271
- pub fn fetch_due_timers(&self) -> MagnusResult<Option<Vec<usize>>> {
272
- call_without_gvl(|| {
273
- let mut timers = self.timers.lock();
274
- let mut io_waiters = self.io_waiters.lock();
275
- let mut due_fibers: Option<Vec<usize>> = None;
276
- while let Some(timer) = timers.peek() {
277
- if timer.is_due() {
278
- due_fibers.get_or_insert_default().push(timer.token.0);
279
- if let Some(waiter) = io_waiters.remove(&timer.token) {
280
- let mut binding = self.registry.lock();
281
- // Pop the current item for the current waiter off the queue
282
- let queue = binding.get_mut(&waiter.fd).unwrap();
283
- queue.pop_front();
284
-
285
- if let Some(head) = queue.get_mut(0) {
286
- // Register the next item in the queue if there is one.
287
- let interest = build_interest(head.readiness)?;
288
- self.poll
289
- .lock()
290
- .registry()
291
- .register(head, head.token, interest)
292
- .map_err(|_| {
293
- ItsiError::ArgumentError("Failed to deregister".to_string())
294
- })?;
295
- } else {
296
- // Otherwise we drop the queue altogether.
297
- binding.remove(&waiter.fd);
298
- }
299
- }
300
- timers.pop();
301
- } else {
302
- break;
303
- }
304
- }
305
- Ok(due_fibers)
306
- })
307
- }
308
- }
@@ -1,38 +0,0 @@
1
- use itsi_scheduler::ItsiScheduler;
2
- use magnus::{function, method, Class, Error, Module, Object, Ruby};
3
- mod itsi_scheduler;
4
-
5
- #[magnus::init]
6
- fn init(ruby: &Ruby) -> Result<(), Error> {
7
- itsi_tracing::init();
8
- let module = ruby.define_module("Itsi")?;
9
- let scheduler = module.define_class("Scheduler", ruby.class_object())?;
10
- scheduler.define_singleton_method("info", function!(ItsiScheduler::class_info, 1))?;
11
- scheduler.define_alloc_func::<ItsiScheduler>();
12
- scheduler.define_method("initialize", method!(ItsiScheduler::initialize, 0))?;
13
- scheduler.define_method("wake", method!(ItsiScheduler::wake, 0))?;
14
- scheduler.define_method(
15
- "register_io_wait",
16
- method!(ItsiScheduler::register_io_wait, 4),
17
- )?;
18
- scheduler.define_method("info", method!(ItsiScheduler::info, 1))?;
19
- scheduler.define_method("debug", method!(ItsiScheduler::debug, 1))?;
20
- scheduler.define_method("warn", method!(ItsiScheduler::warn, 1))?;
21
- scheduler.define_method("start_timer", method!(ItsiScheduler::start_timer, 2))?;
22
- scheduler.define_method(
23
- "address_resolve",
24
- method!(ItsiScheduler::address_resolve, 1),
25
- )?;
26
- scheduler.define_method("has_pending_io?", method!(ItsiScheduler::has_pending_io, 0))?;
27
-
28
- scheduler.define_method(
29
- "fetch_due_timers",
30
- method!(ItsiScheduler::fetch_due_timers, 0),
31
- )?;
32
- scheduler.define_method(
33
- "fetch_due_events",
34
- method!(ItsiScheduler::fetch_due_events, 0),
35
- )?;
36
-
37
- Ok(())
38
- }