@rivetkit/engine 1.0.0

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 (1392) hide show
  1. package/LICENSE +203 -0
  2. package/artifacts/errors/actor.destroyed_during_creation.json +5 -0
  3. package/artifacts/errors/actor.destroyed_while_waiting_for_ready.json +5 -0
  4. package/artifacts/errors/actor.duplicate_key.json +5 -0
  5. package/artifacts/errors/actor.empty_key.json +5 -0
  6. package/artifacts/errors/actor.input_too_large.json +5 -0
  7. package/artifacts/errors/actor.key_reserved_in_different_datacenter.json +5 -0
  8. package/artifacts/errors/actor.key_too_large.json +5 -0
  9. package/artifacts/errors/actor.kv_key_not_found.json +5 -0
  10. package/artifacts/errors/actor.namespace_not_found.json +5 -0
  11. package/artifacts/errors/actor.no_runners_available.json +5 -0
  12. package/artifacts/errors/actor.not_found.json +5 -0
  13. package/artifacts/errors/api.bad_request.json +5 -0
  14. package/artifacts/errors/api.forbidden.json +5 -0
  15. package/artifacts/errors/api.internal_error.json +5 -0
  16. package/artifacts/errors/api.not_found.json +5 -0
  17. package/artifacts/errors/api.rate_limited.json +5 -0
  18. package/artifacts/errors/api.unauthorized.json +5 -0
  19. package/artifacts/errors/datacenter.not_found.json +5 -0
  20. package/artifacts/errors/guard.actor_destroyed.json +5 -0
  21. package/artifacts/errors/guard.actor_not_found.json +5 -0
  22. package/artifacts/errors/guard.actor_ready_timeout.json +5 -0
  23. package/artifacts/errors/guard.connection_error.json +5 -0
  24. package/artifacts/errors/guard.http_request_build_failed.json +5 -0
  25. package/artifacts/errors/guard.missing_header.json +5 -0
  26. package/artifacts/errors/guard.must_use_regional_host.json +5 -0
  27. package/artifacts/errors/guard.no_route.json +5 -0
  28. package/artifacts/errors/guard.no_route_targets.json +5 -0
  29. package/artifacts/errors/guard.rate_limit.json +5 -0
  30. package/artifacts/errors/guard.request_build_error.json +5 -0
  31. package/artifacts/errors/guard.request_timeout.json +5 -0
  32. package/artifacts/errors/guard.retry_attempts_exceeded.json +5 -0
  33. package/artifacts/errors/guard.service_unavailable.json +5 -0
  34. package/artifacts/errors/guard.target_changed.json +5 -0
  35. package/artifacts/errors/guard.upstream_error.json +5 -0
  36. package/artifacts/errors/guard.uri_parse_error.json +5 -0
  37. package/artifacts/errors/guard.websocket_pending_limit_reached.json +5 -0
  38. package/artifacts/errors/guard.websocket_service_hibernate.json +5 -0
  39. package/artifacts/errors/guard.websocket_service_timeout.json +5 -0
  40. package/artifacts/errors/guard.websocket_service_unavailable.json +5 -0
  41. package/artifacts/errors/guard.wrong_addr_protocol.json +5 -0
  42. package/artifacts/errors/kv.leader_forwarding_failed.json +5 -0
  43. package/artifacts/errors/kv.no_leader_elected.json +5 -0
  44. package/artifacts/errors/kv.not_leader.json +5 -0
  45. package/artifacts/errors/kv.response_channel_closed.json +5 -0
  46. package/artifacts/errors/namespace.failed_to_create.json +5 -0
  47. package/artifacts/errors/namespace.invalid_name.json +5 -0
  48. package/artifacts/errors/namespace.invalid_update.json +5 -0
  49. package/artifacts/errors/namespace.name_not_unique.json +5 -0
  50. package/artifacts/errors/namespace.not_found.json +5 -0
  51. package/artifacts/errors/namespace.not_leader.json +5 -0
  52. package/artifacts/errors/runner.not_found.json +5 -0
  53. package/artifacts/errors/runner_config.invalid.json +5 -0
  54. package/artifacts/errors/runner_config.not_found.json +5 -0
  55. package/artifacts/errors/test.input_too_large.json +5 -0
  56. package/artifacts/errors/test.key_too_large.json +5 -0
  57. package/artifacts/errors/test.meta_error.json +5 -0
  58. package/artifacts/errors/test.not_found.json +5 -0
  59. package/artifacts/errors/test.simple_error.json +5 -0
  60. package/artifacts/errors/test.test_error.json +5 -0
  61. package/artifacts/errors/ups.publish_failed.json +5 -0
  62. package/artifacts/errors/ups.request_timeout.json +5 -0
  63. package/artifacts/errors/validation.invalid_input.json +5 -0
  64. package/artifacts/errors/validation.no_keys.json +5 -0
  65. package/artifacts/errors/validation.race_condition.json +5 -0
  66. package/artifacts/errors/validation.too_many_actor_ids.json +5 -0
  67. package/artifacts/errors/ws.connection_closed.json +5 -0
  68. package/artifacts/errors/ws.eviction.json +5 -0
  69. package/artifacts/errors/ws.invalid_initial_packet.json +5 -0
  70. package/artifacts/errors/ws.invalid_packet.json +5 -0
  71. package/artifacts/errors/ws.invalid_url.json +5 -0
  72. package/artifacts/errors/ws.timed_out_waiting_for_init.json +5 -0
  73. package/artifacts/openapi.json +1833 -0
  74. package/contrib-docs/ACTOR_KEY_RESERVATION.md +101 -0
  75. package/contrib-docs/API.md +11 -0
  76. package/contrib-docs/DOCKER.md +5 -0
  77. package/contrib-docs/ERRORS.md +13 -0
  78. package/contrib-docs/GUARD.md +76 -0
  79. package/contrib-docs/PEGBOARD_TUNNEL_RETRIES.md +83 -0
  80. package/contrib-docs/RUNNER_LIFECYCLE.md +172 -0
  81. package/contrib-docs/SDKS.md +9 -0
  82. package/contrib-docs/TEST_DEPENDENCIES.md +43 -0
  83. package/contrib-docs/design-choicse/EMBEDDED_KV.md +80 -0
  84. package/contrib-docs/operate/TRACING_RECONFIGURE.md +78 -0
  85. package/docker/dev/.gitattributes +1 -0
  86. package/docker/dev/README.md +74 -0
  87. package/docker/dev/clickhouse/client-config.xml +5 -0
  88. package/docker/dev/clickhouse/config.xml +52 -0
  89. package/docker/dev/clickhouse/init/01-create-otel-table.sql +107 -0
  90. package/docker/dev/clickhouse/users.xml +35 -0
  91. package/docker/dev/docker-compose.yml +217 -0
  92. package/docker/dev/grafana/dashboards/api.json +1240 -0
  93. package/docker/dev/grafana/dashboards/cache.json +1075 -0
  94. package/docker/dev/grafana/dashboards/futures.json +230 -0
  95. package/docker/dev/grafana/dashboards/gasoline.json +2477 -0
  96. package/docker/dev/grafana/dashboards/guard.json +1274 -0
  97. package/docker/dev/grafana/dashboards/tokio.json +1005 -0
  98. package/docker/dev/grafana/dashboards/traces.json +957 -0
  99. package/docker/dev/grafana/grafana.ini +14 -0
  100. package/docker/dev/grafana/provisioning/dashboards/dashboards.yaml +10 -0
  101. package/docker/dev/grafana/provisioning/datasources/datasources.yaml +30 -0
  102. package/docker/dev/otel-collector-client/config.yaml +39 -0
  103. package/docker/dev/otel-collector-server/config.yaml +72 -0
  104. package/docker/dev/postgres/init-db.sh +6 -0
  105. package/docker/dev/rivet-engine/config.jsonc +48 -0
  106. package/docker/dev/vector-client/vector.yaml +31 -0
  107. package/docker/dev/vector-server/vector.yaml +61 -0
  108. package/docker/dev-host/.gitattributes +1 -0
  109. package/docker/dev-host/README.md +74 -0
  110. package/docker/dev-host/clickhouse/client-config.xml +5 -0
  111. package/docker/dev-host/clickhouse/config.xml +52 -0
  112. package/docker/dev-host/clickhouse/init/01-create-otel-table.sql +107 -0
  113. package/docker/dev-host/clickhouse/users.xml +35 -0
  114. package/docker/dev-host/docker-compose.yml +190 -0
  115. package/docker/dev-host/grafana/dashboards/api.json +1240 -0
  116. package/docker/dev-host/grafana/dashboards/cache.json +1075 -0
  117. package/docker/dev-host/grafana/dashboards/futures.json +230 -0
  118. package/docker/dev-host/grafana/dashboards/gasoline.json +2477 -0
  119. package/docker/dev-host/grafana/dashboards/guard.json +1274 -0
  120. package/docker/dev-host/grafana/dashboards/tokio.json +1005 -0
  121. package/docker/dev-host/grafana/dashboards/traces.json +957 -0
  122. package/docker/dev-host/grafana/grafana.ini +14 -0
  123. package/docker/dev-host/grafana/provisioning/dashboards/dashboards.yaml +10 -0
  124. package/docker/dev-host/grafana/provisioning/datasources/datasources.yaml +30 -0
  125. package/docker/dev-host/otel-collector-client/config.yaml +39 -0
  126. package/docker/dev-host/otel-collector-server/config.yaml +72 -0
  127. package/docker/dev-host/postgres/init-db.sh +6 -0
  128. package/docker/dev-host/rivet-engine/config.jsonc +48 -0
  129. package/docker/dev-host/vector-client/vector.yaml +31 -0
  130. package/docker/dev-host/vector-server/vector.yaml +61 -0
  131. package/docker/dev-multidc/.gitattributes +1 -0
  132. package/docker/dev-multidc/README.md +86 -0
  133. package/docker/dev-multidc/core/clickhouse/client-config.xml +5 -0
  134. package/docker/dev-multidc/core/clickhouse/config.xml +52 -0
  135. package/docker/dev-multidc/core/clickhouse/init/01-create-otel-table.sql +107 -0
  136. package/docker/dev-multidc/core/clickhouse/users.xml +35 -0
  137. package/docker/dev-multidc/core/grafana/dashboards/api.json +1240 -0
  138. package/docker/dev-multidc/core/grafana/dashboards/cache.json +1075 -0
  139. package/docker/dev-multidc/core/grafana/dashboards/futures.json +230 -0
  140. package/docker/dev-multidc/core/grafana/dashboards/gasoline.json +2477 -0
  141. package/docker/dev-multidc/core/grafana/dashboards/guard.json +1274 -0
  142. package/docker/dev-multidc/core/grafana/dashboards/tokio.json +1005 -0
  143. package/docker/dev-multidc/core/grafana/dashboards/traces.json +957 -0
  144. package/docker/dev-multidc/core/grafana/grafana.ini +14 -0
  145. package/docker/dev-multidc/core/grafana/provisioning/dashboards/dashboards.yaml +10 -0
  146. package/docker/dev-multidc/core/grafana/provisioning/datasources/datasources.yaml +30 -0
  147. package/docker/dev-multidc/datacenters/dc-a/otel-collector-client/config.yaml +39 -0
  148. package/docker/dev-multidc/datacenters/dc-a/otel-collector-server/config.yaml +72 -0
  149. package/docker/dev-multidc/datacenters/dc-a/postgres/init-db.sh +6 -0
  150. package/docker/dev-multidc/datacenters/dc-a/rivet-engine/config.jsonc +62 -0
  151. package/docker/dev-multidc/datacenters/dc-a/vector-client/vector.yaml +31 -0
  152. package/docker/dev-multidc/datacenters/dc-a/vector-server/vector.yaml +61 -0
  153. package/docker/dev-multidc/datacenters/dc-b/otel-collector-client/config.yaml +39 -0
  154. package/docker/dev-multidc/datacenters/dc-b/otel-collector-server/config.yaml +72 -0
  155. package/docker/dev-multidc/datacenters/dc-b/postgres/init-db.sh +6 -0
  156. package/docker/dev-multidc/datacenters/dc-b/rivet-engine/config.jsonc +62 -0
  157. package/docker/dev-multidc/datacenters/dc-b/vector-client/vector.yaml +31 -0
  158. package/docker/dev-multidc/datacenters/dc-b/vector-server/vector.yaml +61 -0
  159. package/docker/dev-multidc/datacenters/dc-c/otel-collector-client/config.yaml +39 -0
  160. package/docker/dev-multidc/datacenters/dc-c/otel-collector-server/config.yaml +72 -0
  161. package/docker/dev-multidc/datacenters/dc-c/postgres/init-db.sh +6 -0
  162. package/docker/dev-multidc/datacenters/dc-c/rivet-engine/config.jsonc +62 -0
  163. package/docker/dev-multidc/datacenters/dc-c/vector-client/vector.yaml +31 -0
  164. package/docker/dev-multidc/datacenters/dc-c/vector-server/vector.yaml +61 -0
  165. package/docker/dev-multidc/docker-compose.yml +546 -0
  166. package/docker/dev-multidc-multinode/.gitattributes +1 -0
  167. package/docker/dev-multidc-multinode/README.md +86 -0
  168. package/docker/dev-multidc-multinode/core/clickhouse/client-config.xml +5 -0
  169. package/docker/dev-multidc-multinode/core/clickhouse/config.xml +52 -0
  170. package/docker/dev-multidc-multinode/core/clickhouse/init/01-create-otel-table.sql +107 -0
  171. package/docker/dev-multidc-multinode/core/clickhouse/users.xml +35 -0
  172. package/docker/dev-multidc-multinode/core/grafana/dashboards/api.json +1240 -0
  173. package/docker/dev-multidc-multinode/core/grafana/dashboards/cache.json +1075 -0
  174. package/docker/dev-multidc-multinode/core/grafana/dashboards/futures.json +230 -0
  175. package/docker/dev-multidc-multinode/core/grafana/dashboards/gasoline.json +2477 -0
  176. package/docker/dev-multidc-multinode/core/grafana/dashboards/guard.json +1274 -0
  177. package/docker/dev-multidc-multinode/core/grafana/dashboards/tokio.json +1005 -0
  178. package/docker/dev-multidc-multinode/core/grafana/dashboards/traces.json +957 -0
  179. package/docker/dev-multidc-multinode/core/grafana/grafana.ini +14 -0
  180. package/docker/dev-multidc-multinode/core/grafana/provisioning/dashboards/dashboards.yaml +10 -0
  181. package/docker/dev-multidc-multinode/core/grafana/provisioning/datasources/datasources.yaml +30 -0
  182. package/docker/dev-multidc-multinode/datacenters/dc-a/otel-collector-client/config.yaml +39 -0
  183. package/docker/dev-multidc-multinode/datacenters/dc-a/otel-collector-server/config.yaml +72 -0
  184. package/docker/dev-multidc-multinode/datacenters/dc-a/postgres/init-db.sh +6 -0
  185. package/docker/dev-multidc-multinode/datacenters/dc-a/rivet-engine/0/config.jsonc +62 -0
  186. package/docker/dev-multidc-multinode/datacenters/dc-a/rivet-engine/1/config.jsonc +62 -0
  187. package/docker/dev-multidc-multinode/datacenters/dc-a/rivet-engine/2/config.jsonc +62 -0
  188. package/docker/dev-multidc-multinode/datacenters/dc-a/vector-client/vector.yaml +31 -0
  189. package/docker/dev-multidc-multinode/datacenters/dc-a/vector-server/vector.yaml +61 -0
  190. package/docker/dev-multidc-multinode/datacenters/dc-b/otel-collector-client/config.yaml +39 -0
  191. package/docker/dev-multidc-multinode/datacenters/dc-b/otel-collector-server/config.yaml +72 -0
  192. package/docker/dev-multidc-multinode/datacenters/dc-b/postgres/init-db.sh +6 -0
  193. package/docker/dev-multidc-multinode/datacenters/dc-b/rivet-engine/0/config.jsonc +62 -0
  194. package/docker/dev-multidc-multinode/datacenters/dc-b/rivet-engine/1/config.jsonc +62 -0
  195. package/docker/dev-multidc-multinode/datacenters/dc-b/rivet-engine/2/config.jsonc +62 -0
  196. package/docker/dev-multidc-multinode/datacenters/dc-b/vector-client/vector.yaml +31 -0
  197. package/docker/dev-multidc-multinode/datacenters/dc-b/vector-server/vector.yaml +61 -0
  198. package/docker/dev-multidc-multinode/datacenters/dc-c/otel-collector-client/config.yaml +39 -0
  199. package/docker/dev-multidc-multinode/datacenters/dc-c/otel-collector-server/config.yaml +72 -0
  200. package/docker/dev-multidc-multinode/datacenters/dc-c/postgres/init-db.sh +6 -0
  201. package/docker/dev-multidc-multinode/datacenters/dc-c/rivet-engine/0/config.jsonc +62 -0
  202. package/docker/dev-multidc-multinode/datacenters/dc-c/rivet-engine/1/config.jsonc +62 -0
  203. package/docker/dev-multidc-multinode/datacenters/dc-c/rivet-engine/2/config.jsonc +62 -0
  204. package/docker/dev-multidc-multinode/datacenters/dc-c/vector-client/vector.yaml +31 -0
  205. package/docker/dev-multidc-multinode/datacenters/dc-c/vector-server/vector.yaml +61 -0
  206. package/docker/dev-multidc-multinode/docker-compose.yml +888 -0
  207. package/docker/dev-multinode/.gitattributes +1 -0
  208. package/docker/dev-multinode/README.md +74 -0
  209. package/docker/dev-multinode/clickhouse/client-config.xml +5 -0
  210. package/docker/dev-multinode/clickhouse/config.xml +52 -0
  211. package/docker/dev-multinode/clickhouse/init/01-create-otel-table.sql +107 -0
  212. package/docker/dev-multinode/clickhouse/users.xml +35 -0
  213. package/docker/dev-multinode/docker-compose.yml +323 -0
  214. package/docker/dev-multinode/grafana/dashboards/api.json +1240 -0
  215. package/docker/dev-multinode/grafana/dashboards/cache.json +1075 -0
  216. package/docker/dev-multinode/grafana/dashboards/futures.json +230 -0
  217. package/docker/dev-multinode/grafana/dashboards/gasoline.json +2477 -0
  218. package/docker/dev-multinode/grafana/dashboards/guard.json +1274 -0
  219. package/docker/dev-multinode/grafana/dashboards/tokio.json +1005 -0
  220. package/docker/dev-multinode/grafana/dashboards/traces.json +957 -0
  221. package/docker/dev-multinode/grafana/grafana.ini +14 -0
  222. package/docker/dev-multinode/grafana/provisioning/dashboards/dashboards.yaml +10 -0
  223. package/docker/dev-multinode/grafana/provisioning/datasources/datasources.yaml +30 -0
  224. package/docker/dev-multinode/otel-collector-client/config.yaml +39 -0
  225. package/docker/dev-multinode/otel-collector-server/config.yaml +72 -0
  226. package/docker/dev-multinode/postgres/init-db.sh +6 -0
  227. package/docker/dev-multinode/rivet-engine/0/config.jsonc +48 -0
  228. package/docker/dev-multinode/rivet-engine/1/config.jsonc +48 -0
  229. package/docker/dev-multinode/rivet-engine/2/config.jsonc +48 -0
  230. package/docker/dev-multinode/vector-client/vector.yaml +31 -0
  231. package/docker/dev-multinode/vector-server/vector.yaml +61 -0
  232. package/docker/engine/build.sh +67 -0
  233. package/docker/engine/linux-aarch64.Dockerfile +97 -0
  234. package/docker/engine/linux-x86_64.Dockerfile +93 -0
  235. package/docker/engine/macos-aarch64.Dockerfile +92 -0
  236. package/docker/engine/macos-x86_64.Dockerfile +92 -0
  237. package/docker/engine/windows.Dockerfile +80 -0
  238. package/docker/prod-file-system/.gitattributes +1 -0
  239. package/docker/prod-file-system/README.md +76 -0
  240. package/docker/prod-file-system/docker-compose.yml +41 -0
  241. package/docker/prod-file-system/rivet-engine/config.jsonc +2 -0
  242. package/docker/template/README.md +20 -0
  243. package/docker/template/grafana-dashboards/api.json +1240 -0
  244. package/docker/template/grafana-dashboards/cache.json +1075 -0
  245. package/docker/template/grafana-dashboards/futures.json +230 -0
  246. package/docker/template/grafana-dashboards/gasoline.json +2477 -0
  247. package/docker/template/grafana-dashboards/guard.json +1274 -0
  248. package/docker/template/grafana-dashboards/tokio.json +1005 -0
  249. package/docker/template/grafana-dashboards/traces.json +957 -0
  250. package/docker/template/node_modules/.bin/js-yaml +21 -0
  251. package/docker/template/node_modules/.bin/tsc +21 -0
  252. package/docker/template/node_modules/.bin/tsserver +21 -0
  253. package/docker/template/node_modules/.bin/tsx +21 -0
  254. package/docker/template/package.json +23 -0
  255. package/docker/template/src/config.ts +104 -0
  256. package/docker/template/src/context.ts +216 -0
  257. package/docker/template/src/docker-compose.ts +368 -0
  258. package/docker/template/src/git.ts +8 -0
  259. package/docker/template/src/main.ts +65 -0
  260. package/docker/template/src/readme.ts +98 -0
  261. package/docker/template/src/services/core/clickhouse.ts +223 -0
  262. package/docker/template/src/services/core/grafana.ts +115 -0
  263. package/docker/template/src/services/edge/otel-collector-client.ts +64 -0
  264. package/docker/template/src/services/edge/otel-collector-server.ts +107 -0
  265. package/docker/template/src/services/edge/postgres.ts +23 -0
  266. package/docker/template/src/services/edge/rivet-engine.ts +87 -0
  267. package/docker/template/src/services/edge/runner.ts +7 -0
  268. package/docker/template/src/services/edge/vector-client.ts +55 -0
  269. package/docker/template/src/services/edge/vector-server.ts +111 -0
  270. package/docker/template/src/utils.ts +19 -0
  271. package/docker/template/tsconfig.json +18 -0
  272. package/docker/universal/Dockerfile +133 -0
  273. package/package.json +10 -0
  274. package/packages/actor-kv/Cargo.toml +31 -0
  275. package/packages/actor-kv/src/entry.rs +147 -0
  276. package/packages/actor-kv/src/key.rs +81 -0
  277. package/packages/actor-kv/src/lib.rs +357 -0
  278. package/packages/actor-kv/src/utils.rs +101 -0
  279. package/packages/actor-kv/tests/kv_operations.rs +294 -0
  280. package/packages/actor-kv/tests/list_edge_cases.rs +370 -0
  281. package/packages/api-builder/Cargo.toml +36 -0
  282. package/packages/api-builder/src/context.rs +98 -0
  283. package/packages/api-builder/src/error_response.rs +116 -0
  284. package/packages/api-builder/src/errors.rs +29 -0
  285. package/packages/api-builder/src/extract.rs +137 -0
  286. package/packages/api-builder/src/global_context.rs +31 -0
  287. package/packages/api-builder/src/lib.rs +19 -0
  288. package/packages/api-builder/src/metrics.rs +29 -0
  289. package/packages/api-builder/src/middleware.rs +232 -0
  290. package/packages/api-builder/src/prelude.rs +18 -0
  291. package/packages/api-builder/src/request_ids.rs +17 -0
  292. package/packages/api-builder/src/router.rs +89 -0
  293. package/packages/api-builder/src/wrappers.rs +138 -0
  294. package/packages/api-builder/tests/basic.rs +215 -0
  295. package/packages/api-builder/tests/errors.rs +104 -0
  296. package/packages/api-peer/Cargo.toml +34 -0
  297. package/packages/api-peer/src/actors/create.rs +40 -0
  298. package/packages/api-peer/src/actors/delete.rs +87 -0
  299. package/packages/api-peer/src/actors/kv_get.rs +67 -0
  300. package/packages/api-peer/src/actors/list.rs +98 -0
  301. package/packages/api-peer/src/actors/list_names.rs +56 -0
  302. package/packages/api-peer/src/actors/mod.rs +5 -0
  303. package/packages/api-peer/src/internal.rs +186 -0
  304. package/packages/api-peer/src/lib.rs +28 -0
  305. package/packages/api-peer/src/namespaces.rs +122 -0
  306. package/packages/api-peer/src/router.rs +51 -0
  307. package/packages/api-peer/src/runner_configs.rs +160 -0
  308. package/packages/api-peer/src/runners.rs +109 -0
  309. package/packages/api-public/Cargo.toml +38 -0
  310. package/packages/api-public/build.rs +45 -0
  311. package/packages/api-public/src/actors/create.rs +99 -0
  312. package/packages/api-public/src/actors/delete.rs +86 -0
  313. package/packages/api-public/src/actors/get_or_create.rs +170 -0
  314. package/packages/api-public/src/actors/kv_get.rs +79 -0
  315. package/packages/api-public/src/actors/list.rs +241 -0
  316. package/packages/api-public/src/actors/list_names.rs +76 -0
  317. package/packages/api-public/src/actors/mod.rs +7 -0
  318. package/packages/api-public/src/actors/utils.rs +216 -0
  319. package/packages/api-public/src/ctx.rs +70 -0
  320. package/packages/api-public/src/datacenters.rs +43 -0
  321. package/packages/api-public/src/errors.rs +30 -0
  322. package/packages/api-public/src/health.rs +166 -0
  323. package/packages/api-public/src/lib.rs +13 -0
  324. package/packages/api-public/src/metadata.rs +24 -0
  325. package/packages/api-public/src/namespaces.rs +89 -0
  326. package/packages/api-public/src/router.rs +182 -0
  327. package/packages/api-public/src/runner_configs/delete.rs +99 -0
  328. package/packages/api-public/src/runner_configs/list.rs +98 -0
  329. package/packages/api-public/src/runner_configs/mod.rs +12 -0
  330. package/packages/api-public/src/runner_configs/refresh_metadata.rs +116 -0
  331. package/packages/api-public/src/runner_configs/serverless_health_check.rs +81 -0
  332. package/packages/api-public/src/runner_configs/upsert.rs +194 -0
  333. package/packages/api-public/src/runner_configs/utils.rs +217 -0
  334. package/packages/api-public/src/runners.rs +144 -0
  335. package/packages/api-public/src/ui.rs +44 -0
  336. package/packages/api-types/Cargo.toml +17 -0
  337. package/packages/api-types/src/actors/create.rs +29 -0
  338. package/packages/api-types/src/actors/list.rs +23 -0
  339. package/packages/api-types/src/actors/list_names.rs +24 -0
  340. package/packages/api-types/src/actors/mod.rs +3 -0
  341. package/packages/api-types/src/datacenters/list.rs +12 -0
  342. package/packages/api-types/src/datacenters/mod.rs +1 -0
  343. package/packages/api-types/src/lib.rs +6 -0
  344. package/packages/api-types/src/namespaces/list.rs +21 -0
  345. package/packages/api-types/src/namespaces/mod.rs +2 -0
  346. package/packages/api-types/src/namespaces/runner_configs.rs +55 -0
  347. package/packages/api-types/src/pagination.rs +8 -0
  348. package/packages/api-types/src/runner_configs/list.rs +29 -0
  349. package/packages/api-types/src/runner_configs/mod.rs +1 -0
  350. package/packages/api-types/src/runners/list.rs +25 -0
  351. package/packages/api-types/src/runners/mod.rs +1 -0
  352. package/packages/api-util/Cargo.toml +22 -0
  353. package/packages/api-util/src/errors.rs +9 -0
  354. package/packages/api-util/src/lib.rs +209 -0
  355. package/packages/bootstrap/Cargo.toml +19 -0
  356. package/packages/bootstrap/src/lib.rs +102 -0
  357. package/packages/cache/Cargo.toml +28 -0
  358. package/packages/cache/src/driver.rs +346 -0
  359. package/packages/cache/src/errors.rs +23 -0
  360. package/packages/cache/src/getter_ctx.rs +138 -0
  361. package/packages/cache/src/inner.rs +60 -0
  362. package/packages/cache/src/key.rs +101 -0
  363. package/packages/cache/src/lib.rs +19 -0
  364. package/packages/cache/src/metrics.rs +34 -0
  365. package/packages/cache/src/purge.rs +13 -0
  366. package/packages/cache/src/rate_limit.rs +109 -0
  367. package/packages/cache/src/req_config.rs +443 -0
  368. package/packages/cache/tests/integration.rs +582 -0
  369. package/packages/cache-purge/Cargo.toml +17 -0
  370. package/packages/cache-purge/src/lib.rs +44 -0
  371. package/packages/cache-result/Cargo.toml +9 -0
  372. package/packages/cache-result/src/lib.rs +61 -0
  373. package/packages/clickhouse-inserter/Cargo.toml +17 -0
  374. package/packages/clickhouse-inserter/src/error.rs +16 -0
  375. package/packages/clickhouse-inserter/src/lib.rs +179 -0
  376. package/packages/clickhouse-user-query/Cargo.toml +16 -0
  377. package/packages/clickhouse-user-query/examples/case_sensitivity_demo.rs +100 -0
  378. package/packages/clickhouse-user-query/examples/group_by_example.rs +53 -0
  379. package/packages/clickhouse-user-query/examples/string_contains_demo.rs +96 -0
  380. package/packages/clickhouse-user-query/src/builder.rs +445 -0
  381. package/packages/clickhouse-user-query/src/error.rs +37 -0
  382. package/packages/clickhouse-user-query/src/lib.rs +61 -0
  383. package/packages/clickhouse-user-query/src/query.rs +143 -0
  384. package/packages/clickhouse-user-query/src/schema.rs +78 -0
  385. package/packages/clickhouse-user-query/tests/builder_tests.rs +619 -0
  386. package/packages/clickhouse-user-query/tests/case_sensitivity_tests.rs +307 -0
  387. package/packages/clickhouse-user-query/tests/integration_tests.rs +540 -0
  388. package/packages/clickhouse-user-query/tests/query_tests.rs +263 -0
  389. package/packages/clickhouse-user-query/tests/schema_tests.rs +44 -0
  390. package/packages/config/Cargo.toml +20 -0
  391. package/packages/config/src/config/api_peer.rs +21 -0
  392. package/packages/config/src/config/api_public.rs +25 -0
  393. package/packages/config/src/config/auth.rs +10 -0
  394. package/packages/config/src/config/cache.rs +24 -0
  395. package/packages/config/src/config/clickhouse.rs +49 -0
  396. package/packages/config/src/config/db.rs +52 -0
  397. package/packages/config/src/config/guard.rs +42 -0
  398. package/packages/config/src/config/logs.rs +10 -0
  399. package/packages/config/src/config/mod.rs +240 -0
  400. package/packages/config/src/config/pegboard.rs +94 -0
  401. package/packages/config/src/config/pubsub.rs +90 -0
  402. package/packages/config/src/config/runtime.rs +31 -0
  403. package/packages/config/src/config/telemetry.rs +14 -0
  404. package/packages/config/src/config/topology.rs +123 -0
  405. package/packages/config/src/config/vector.rs +18 -0
  406. package/packages/config/src/defaults.rs +11 -0
  407. package/packages/config/src/lib.rs +135 -0
  408. package/packages/config/src/paths.rs +25 -0
  409. package/packages/config/src/secret.rs +72 -0
  410. package/packages/dump-openapi/Cargo.toml +11 -0
  411. package/packages/dump-openapi/build.rs +26 -0
  412. package/packages/dump-openapi/src/lib.rs +1 -0
  413. package/packages/engine/Cargo.toml +74 -0
  414. package/packages/engine/src/commands/config.rs +18 -0
  415. package/packages/engine/src/commands/db/mod.rs +80 -0
  416. package/packages/engine/src/commands/mod.rs +7 -0
  417. package/packages/engine/src/commands/start.rs +143 -0
  418. package/packages/engine/src/commands/tracing.rs +86 -0
  419. package/packages/engine/src/commands/udb/cli.rs +562 -0
  420. package/packages/engine/src/commands/udb/mod.rs +132 -0
  421. package/packages/engine/src/commands/udb_keys.rs +200 -0
  422. package/packages/engine/src/commands/wf/mod.rs +125 -0
  423. package/packages/engine/src/commands/wf/signal.rs +80 -0
  424. package/packages/engine/src/keys.rs +47 -0
  425. package/packages/engine/src/lib.rs +55 -0
  426. package/packages/engine/src/main.rs +60 -0
  427. package/packages/engine/src/run_config.rs +53 -0
  428. package/packages/engine/src/util/db.rs +99 -0
  429. package/packages/engine/src/util/format.rs +69 -0
  430. package/packages/engine/src/util/mod.rs +13 -0
  431. package/packages/engine/src/util/udb.rs +687 -0
  432. package/packages/engine/src/util/wf/mod.rs +649 -0
  433. package/packages/engine/src/util/wf/signal.rs +126 -0
  434. package/packages/engine/tests/actors_create.rs +524 -0
  435. package/packages/engine/tests/actors_delete.rs +243 -0
  436. package/packages/engine/tests/actors_general.rs +191 -0
  437. package/packages/engine/tests/actors_get.rs +230 -0
  438. package/packages/engine/tests/actors_get_by_id.rs +170 -0
  439. package/packages/engine/tests/actors_get_or_create.rs +294 -0
  440. package/packages/engine/tests/actors_get_or_create_by_id.rs +147 -0
  441. package/packages/engine/tests/actors_lifecycle.rs +165 -0
  442. package/packages/engine/tests/actors_list.rs +798 -0
  443. package/packages/engine/tests/actors_list_names.rs +353 -0
  444. package/packages/engine/tests/common/actors.rs +554 -0
  445. package/packages/engine/tests/common/ctx.rs +201 -0
  446. package/packages/engine/tests/common/mod.rs +30 -0
  447. package/packages/engine/tests/common/ns.rs +36 -0
  448. package/packages/engine/tests/common/runner.rs +134 -0
  449. package/packages/engine/tests/common/test_helpers.rs +226 -0
  450. package/packages/engine/tests/runners_dupe_key.rs +27 -0
  451. package/packages/engine/tests/runners_version.rs +50 -0
  452. package/packages/env/Cargo.toml +14 -0
  453. package/packages/env/build.rs +8 -0
  454. package/packages/env/src/lib.rs +30 -0
  455. package/packages/epoxy/Cargo.toml +45 -0
  456. package/packages/epoxy/README.md +158 -0
  457. package/packages/epoxy/spec/KEYS.md +33 -0
  458. package/packages/epoxy/spec/PROPOSAL.md +125 -0
  459. package/packages/epoxy/spec/RECONFIGURE.md +40 -0
  460. package/packages/epoxy/src/consts.rs +42 -0
  461. package/packages/epoxy/src/errors.rs +21 -0
  462. package/packages/epoxy/src/http_client.rs +192 -0
  463. package/packages/epoxy/src/http_routes.rs +34 -0
  464. package/packages/epoxy/src/keys/keys.rs +99 -0
  465. package/packages/epoxy/src/keys/mod.rs +9 -0
  466. package/packages/epoxy/src/keys/replica.rs +283 -0
  467. package/packages/epoxy/src/lib.rs +25 -0
  468. package/packages/epoxy/src/ops/explicit_prepare.rs +342 -0
  469. package/packages/epoxy/src/ops/kv/get_local.rs +44 -0
  470. package/packages/epoxy/src/ops/kv/get_optimistic.rs +150 -0
  471. package/packages/epoxy/src/ops/kv/mod.rs +3 -0
  472. package/packages/epoxy/src/ops/kv/purge_local.rs +28 -0
  473. package/packages/epoxy/src/ops/mod.rs +4 -0
  474. package/packages/epoxy/src/ops/propose.rs +352 -0
  475. package/packages/epoxy/src/ops/read_cluster_config.rs +24 -0
  476. package/packages/epoxy/src/replica/ballot.rs +130 -0
  477. package/packages/epoxy/src/replica/commit_kv.rs +80 -0
  478. package/packages/epoxy/src/replica/decide_path.rs +51 -0
  479. package/packages/epoxy/src/replica/lead_consensus.rs +65 -0
  480. package/packages/epoxy/src/replica/log.rs +84 -0
  481. package/packages/epoxy/src/replica/message_request.rs +166 -0
  482. package/packages/epoxy/src/replica/messages/accept.rs +50 -0
  483. package/packages/epoxy/src/replica/messages/accepted.rs +35 -0
  484. package/packages/epoxy/src/replica/messages/commit.rs +46 -0
  485. package/packages/epoxy/src/replica/messages/committed.rs +41 -0
  486. package/packages/epoxy/src/replica/messages/download_instances.rs +69 -0
  487. package/packages/epoxy/src/replica/messages/mod.rs +15 -0
  488. package/packages/epoxy/src/replica/messages/pre_accept.rs +69 -0
  489. package/packages/epoxy/src/replica/messages/prepare.rs +89 -0
  490. package/packages/epoxy/src/replica/mod.rs +11 -0
  491. package/packages/epoxy/src/replica/update_config.rs +24 -0
  492. package/packages/epoxy/src/replica/utils.rs +111 -0
  493. package/packages/epoxy/src/types.rs +117 -0
  494. package/packages/epoxy/src/utils.rs +65 -0
  495. package/packages/epoxy/src/workflows/coordinator/mod.rs +121 -0
  496. package/packages/epoxy/src/workflows/coordinator/reconfigure.rs +291 -0
  497. package/packages/epoxy/src/workflows/coordinator/replica_status_change.rs +193 -0
  498. package/packages/epoxy/src/workflows/mod.rs +3 -0
  499. package/packages/epoxy/src/workflows/purger.rs +81 -0
  500. package/packages/epoxy/src/workflows/replica/mod.rs +39 -0
  501. package/packages/epoxy/src/workflows/replica/setup.rs +823 -0
  502. package/packages/epoxy/tests/common/api.rs +25 -0
  503. package/packages/epoxy/tests/common/mod.rs +301 -0
  504. package/packages/epoxy/tests/common/utils.rs +23 -0
  505. package/packages/epoxy/tests/kv.rs +187 -0
  506. package/packages/epoxy/tests/kv_get_optimistic.rs +179 -0
  507. package/packages/epoxy/tests/proposal.rs +38 -0
  508. package/packages/epoxy/tests/reconfigure.rs +618 -0
  509. package/packages/error/Cargo.toml +16 -0
  510. package/packages/error/src/error.rs +90 -0
  511. package/packages/error/src/lib.rs +13 -0
  512. package/packages/error/src/schema.rs +86 -0
  513. package/packages/error/tests/basic.rs +338 -0
  514. package/packages/error-macros/Cargo.toml +19 -0
  515. package/packages/error-macros/src/lib.rs +632 -0
  516. package/packages/gasoline/Cargo.toml +55 -0
  517. package/packages/gasoline/src/activity.rs +24 -0
  518. package/packages/gasoline/src/builder/common/message.rs +104 -0
  519. package/packages/gasoline/src/builder/common/mod.rs +5 -0
  520. package/packages/gasoline/src/builder/common/signal.rs +193 -0
  521. package/packages/gasoline/src/builder/common/workflow.rs +196 -0
  522. package/packages/gasoline/src/builder/mod.rs +60 -0
  523. package/packages/gasoline/src/builder/workflow/message.rs +147 -0
  524. package/packages/gasoline/src/builder/workflow/mod.rs +5 -0
  525. package/packages/gasoline/src/builder/workflow/signal.rs +227 -0
  526. package/packages/gasoline/src/builder/workflow/sub_workflow.rs +318 -0
  527. package/packages/gasoline/src/ctx/activity.rs +192 -0
  528. package/packages/gasoline/src/ctx/common.rs +153 -0
  529. package/packages/gasoline/src/ctx/listen.rs +121 -0
  530. package/packages/gasoline/src/ctx/message.rs +346 -0
  531. package/packages/gasoline/src/ctx/mod.rs +18 -0
  532. package/packages/gasoline/src/ctx/operation.rs +191 -0
  533. package/packages/gasoline/src/ctx/standalone.rs +228 -0
  534. package/packages/gasoline/src/ctx/test.rs +251 -0
  535. package/packages/gasoline/src/ctx/versioned_workflow.rs +198 -0
  536. package/packages/gasoline/src/ctx/workflow.rs +1459 -0
  537. package/packages/gasoline/src/db/debug.rs +199 -0
  538. package/packages/gasoline/src/db/kv/debug.rs +1493 -0
  539. package/packages/gasoline/src/db/kv/keys/history.rs +1780 -0
  540. package/packages/gasoline/src/db/kv/keys/metric.rs +170 -0
  541. package/packages/gasoline/src/db/kv/keys/mod.rs +6 -0
  542. package/packages/gasoline/src/db/kv/keys/signal.rs +401 -0
  543. package/packages/gasoline/src/db/kv/keys/wake.rs +310 -0
  544. package/packages/gasoline/src/db/kv/keys/worker.rs +185 -0
  545. package/packages/gasoline/src/db/kv/keys/workflow.rs +1175 -0
  546. package/packages/gasoline/src/db/kv/mod.rs +3044 -0
  547. package/packages/gasoline/src/db/kv/subjects.rs +13 -0
  548. package/packages/gasoline/src/db/kv/system.rs +33 -0
  549. package/packages/gasoline/src/db/mod.rs +344 -0
  550. package/packages/gasoline/src/error.rs +258 -0
  551. package/packages/gasoline/src/executable.rs +186 -0
  552. package/packages/gasoline/src/history/cursor.rs +779 -0
  553. package/packages/gasoline/src/history/event.rs +210 -0
  554. package/packages/gasoline/src/history/location.rs +185 -0
  555. package/packages/gasoline/src/history/mod.rs +8 -0
  556. package/packages/gasoline/src/history/removed.rs +94 -0
  557. package/packages/gasoline/src/lib.rs +18 -0
  558. package/packages/gasoline/src/listen.rs +24 -0
  559. package/packages/gasoline/src/message.rs +103 -0
  560. package/packages/gasoline/src/metrics.rs +156 -0
  561. package/packages/gasoline/src/operation.rs +21 -0
  562. package/packages/gasoline/src/prelude.rs +53 -0
  563. package/packages/gasoline/src/registry.rs +111 -0
  564. package/packages/gasoline/src/signal.rs +117 -0
  565. package/packages/gasoline/src/stub.rs +118 -0
  566. package/packages/gasoline/src/utils/mod.rs +20 -0
  567. package/packages/gasoline/src/utils/tags.rs +82 -0
  568. package/packages/gasoline/src/utils/time.rs +85 -0
  569. package/packages/gasoline/src/worker.rs +336 -0
  570. package/packages/gasoline/src/workflow.rs +64 -0
  571. package/packages/gasoline/tests/activity_ctx.rs +83 -0
  572. package/packages/gasoline/tests/workflow_ctx.rs +288 -0
  573. package/packages/gasoline/tests/workflows/activity_test.rs +33 -0
  574. package/packages/gasoline/tests/workflows/basic.rs +13 -0
  575. package/packages/gasoline/tests/workflows/eviction_test.rs +45 -0
  576. package/packages/gasoline/tests/workflows/listen_timeout.rs +27 -0
  577. package/packages/gasoline/tests/workflows/loop_test.rs +30 -0
  578. package/packages/gasoline/tests/workflows/mod.rs +11 -0
  579. package/packages/gasoline/tests/workflows/properties_test.rs +56 -0
  580. package/packages/gasoline/tests/workflows/signal_test.rs +24 -0
  581. package/packages/gasoline/tests/workflows/sleep_test.rs +15 -0
  582. package/packages/gasoline/tests/workflows/state_test.rs +69 -0
  583. package/packages/gasoline/tests/workflows/sub_test.rs +21 -0
  584. package/packages/gasoline/tests/workflows/tags_test.rs +40 -0
  585. package/packages/gasoline-macros/Cargo.toml +14 -0
  586. package/packages/gasoline-macros/src/lib.rs +527 -0
  587. package/packages/guard/Cargo.toml +56 -0
  588. package/packages/guard/src/cache/actor.rs +43 -0
  589. package/packages/guard/src/cache/mod.rs +69 -0
  590. package/packages/guard/src/errors.rs +62 -0
  591. package/packages/guard/src/lib.rs +58 -0
  592. package/packages/guard/src/middleware.rs +42 -0
  593. package/packages/guard/src/routing/api_public.rs +70 -0
  594. package/packages/guard/src/routing/mod.rs +245 -0
  595. package/packages/guard/src/routing/pegboard_gateway.rs +260 -0
  596. package/packages/guard/src/routing/runner.rs +129 -0
  597. package/packages/guard/src/shared_state.rs +31 -0
  598. package/packages/guard/src/tls.rs +224 -0
  599. package/packages/guard/tests/parse_actor_path.rs +240 -0
  600. package/packages/guard-core/Cargo.toml +58 -0
  601. package/packages/guard-core/src/analytics.rs +46 -0
  602. package/packages/guard-core/src/cert_resolver.rs +61 -0
  603. package/packages/guard-core/src/custom_serve.rs +52 -0
  604. package/packages/guard-core/src/errors.rs +113 -0
  605. package/packages/guard-core/src/lib.rs +25 -0
  606. package/packages/guard-core/src/metrics.rs +64 -0
  607. package/packages/guard-core/src/proxy_service.rs +2699 -0
  608. package/packages/guard-core/src/request_context.rs +184 -0
  609. package/packages/guard-core/src/server.rs +289 -0
  610. package/packages/guard-core/src/task_group.rs +57 -0
  611. package/packages/guard-core/src/types.rs +19 -0
  612. package/packages/guard-core/src/websocket_handle.rs +47 -0
  613. package/packages/guard-core/tests/common/mod.rs +678 -0
  614. package/packages/guard-core/tests/custom_serve.rs +392 -0
  615. package/packages/guard-core/tests/fixtures/tls/README.md +6 -0
  616. package/packages/guard-core/tests/fixtures/tls/api_cert.pem +51 -0
  617. package/packages/guard-core/tests/fixtures/tls/api_key.pem +7 -0
  618. package/packages/guard-core/tests/fixtures/tls/job_cert.pem +55 -0
  619. package/packages/guard-core/tests/fixtures/tls/job_key.pem +7 -0
  620. package/packages/guard-core/tests/https.rs +400 -0
  621. package/packages/guard-core/tests/metrics.rs +247 -0
  622. package/packages/guard-core/tests/proxy.rs +842 -0
  623. package/packages/guard-core/tests/simple_websocket.rs +258 -0
  624. package/packages/guard-core/tests/simple_websocket_echo.rs +318 -0
  625. package/packages/guard-core/tests/simple_websocket_test2.rs +120 -0
  626. package/packages/guard-core/tests/streaming_response.rs +265 -0
  627. package/packages/guard-core/tests/websocket.rs +1113 -0
  628. package/packages/internal/Cargo.toml +13 -0
  629. package/packages/internal/README.md +1 -0
  630. package/packages/internal/src/lib.rs +1 -0
  631. package/packages/internal/src/ops/bump_serverless_autoscaler_global.rs +64 -0
  632. package/packages/internal/src/ops/cache/mod.rs +1 -0
  633. package/packages/internal/src/ops/cache/purge_global.rs +81 -0
  634. package/packages/internal/src/ops/mod.rs +2 -0
  635. package/packages/logs/Cargo.toml +20 -0
  636. package/packages/logs/src/lib.rs +9 -0
  637. package/packages/logs/src/unix.rs +201 -0
  638. package/packages/logs/src/windows.rs +240 -0
  639. package/packages/metrics/Cargo.toml +20 -0
  640. package/packages/metrics/src/buckets.rs +32 -0
  641. package/packages/metrics/src/lib.rs +8 -0
  642. package/packages/metrics/src/providers.rs +183 -0
  643. package/packages/namespace/Cargo.toml +28 -0
  644. package/packages/namespace/src/errors.rs +39 -0
  645. package/packages/namespace/src/keys/mod.rs +190 -0
  646. package/packages/namespace/src/keys/runner_config.rs +211 -0
  647. package/packages/namespace/src/lib.rs +16 -0
  648. package/packages/namespace/src/ops/get_global.rs +58 -0
  649. package/packages/namespace/src/ops/get_local.rs +69 -0
  650. package/packages/namespace/src/ops/list.rs +69 -0
  651. package/packages/namespace/src/ops/mod.rs +6 -0
  652. package/packages/namespace/src/ops/resolve_for_name_global.rs +57 -0
  653. package/packages/namespace/src/ops/resolve_for_name_local.rs +41 -0
  654. package/packages/namespace/src/ops/runner_config/delete.rs +53 -0
  655. package/packages/namespace/src/ops/runner_config/get.rs +94 -0
  656. package/packages/namespace/src/ops/runner_config/list.rs +94 -0
  657. package/packages/namespace/src/ops/runner_config/mod.rs +4 -0
  658. package/packages/namespace/src/ops/runner_config/upsert.rs +148 -0
  659. package/packages/namespace/src/utils.rs +11 -0
  660. package/packages/namespace/src/workflows/mod.rs +1 -0
  661. package/packages/namespace/src/workflows/namespace.rs +178 -0
  662. package/packages/pegboard/Cargo.toml +34 -0
  663. package/packages/pegboard/src/errors.rs +76 -0
  664. package/packages/pegboard/src/keys/actor.rs +443 -0
  665. package/packages/pegboard/src/keys/epoxy/mod.rs +1 -0
  666. package/packages/pegboard/src/keys/epoxy/ns.rs +68 -0
  667. package/packages/pegboard/src/keys/hibernating_request.rs +72 -0
  668. package/packages/pegboard/src/keys/mod.rs +15 -0
  669. package/packages/pegboard/src/keys/ns.rs +1367 -0
  670. package/packages/pegboard/src/keys/runner.rs +818 -0
  671. package/packages/pegboard/src/lib.rs +19 -0
  672. package/packages/pegboard/src/metrics.rs +19 -0
  673. package/packages/pegboard/src/ops/actor/create.rs +159 -0
  674. package/packages/pegboard/src/ops/actor/get.rs +100 -0
  675. package/packages/pegboard/src/ops/actor/get_for_gateway.rs +70 -0
  676. package/packages/pegboard/src/ops/actor/get_for_key.rs +93 -0
  677. package/packages/pegboard/src/ops/actor/get_reservation_for_key.rs +46 -0
  678. package/packages/pegboard/src/ops/actor/get_runner.rs +64 -0
  679. package/packages/pegboard/src/ops/actor/hibernating_request/delete.rs +41 -0
  680. package/packages/pegboard/src/ops/actor/hibernating_request/list.rs +65 -0
  681. package/packages/pegboard/src/ops/actor/hibernating_request/mod.rs +3 -0
  682. package/packages/pegboard/src/ops/actor/hibernating_request/upsert.rs +51 -0
  683. package/packages/pegboard/src/ops/actor/list_for_ns.rs +207 -0
  684. package/packages/pegboard/src/ops/actor/list_names.rs +62 -0
  685. package/packages/pegboard/src/ops/actor/mod.rs +9 -0
  686. package/packages/pegboard/src/ops/mod.rs +2 -0
  687. package/packages/pegboard/src/ops/runner/find_dc_with_runner.rs +222 -0
  688. package/packages/pegboard/src/ops/runner/get.rs +143 -0
  689. package/packages/pegboard/src/ops/runner/get_by_key.rs +51 -0
  690. package/packages/pegboard/src/ops/runner/list_for_ns.rs +209 -0
  691. package/packages/pegboard/src/ops/runner/list_names.rs +60 -0
  692. package/packages/pegboard/src/ops/runner/mod.rs +6 -0
  693. package/packages/pegboard/src/ops/runner/update_alloc_idx.rs +208 -0
  694. package/packages/pegboard/src/pubsub_subjects.rs +80 -0
  695. package/packages/pegboard/src/utils.rs +29 -0
  696. package/packages/pegboard/src/workflows/actor/destroy.rs +264 -0
  697. package/packages/pegboard/src/workflows/actor/keys.rs +283 -0
  698. package/packages/pegboard/src/workflows/actor/mod.rs +804 -0
  699. package/packages/pegboard/src/workflows/actor/runtime.rs +909 -0
  700. package/packages/pegboard/src/workflows/actor/setup.rs +175 -0
  701. package/packages/pegboard/src/workflows/mod.rs +2 -0
  702. package/packages/pegboard/src/workflows/runner.rs +1182 -0
  703. package/packages/pegboard-gateway/Cargo.toml +35 -0
  704. package/packages/pegboard-gateway/src/keepalive_task.rs +61 -0
  705. package/packages/pegboard-gateway/src/lib.rs +698 -0
  706. package/packages/pegboard-gateway/src/metrics.rs +14 -0
  707. package/packages/pegboard-gateway/src/ping_task.rs +23 -0
  708. package/packages/pegboard-gateway/src/shared_state.rs +588 -0
  709. package/packages/pegboard-gateway/src/tunnel_to_ws_task.rs +85 -0
  710. package/packages/pegboard-gateway/src/ws_to_tunnel_task.rs +65 -0
  711. package/packages/pegboard-runner/Cargo.toml +38 -0
  712. package/packages/pegboard-runner/src/conn.rs +183 -0
  713. package/packages/pegboard-runner/src/errors.rs +33 -0
  714. package/packages/pegboard-runner/src/lib.rs +249 -0
  715. package/packages/pegboard-runner/src/ping_task.rs +66 -0
  716. package/packages/pegboard-runner/src/tunnel_to_ws_task.rs +137 -0
  717. package/packages/pegboard-runner/src/utils.rs +40 -0
  718. package/packages/pegboard-runner/src/ws_to_tunnel_task.rs +443 -0
  719. package/packages/pegboard-serverless/Cargo.toml +25 -0
  720. package/packages/pegboard-serverless/src/lib.rs +523 -0
  721. package/packages/pools/Cargo.toml +38 -0
  722. package/packages/pools/src/db/clickhouse.rs +37 -0
  723. package/packages/pools/src/db/mod.rs +3 -0
  724. package/packages/pools/src/db/udb.rs +37 -0
  725. package/packages/pools/src/db/ups.rs +91 -0
  726. package/packages/pools/src/error.rs +41 -0
  727. package/packages/pools/src/lib.rs +16 -0
  728. package/packages/pools/src/metrics.rs +32 -0
  729. package/packages/pools/src/pools.rs +114 -0
  730. package/packages/pools/src/prelude.rs +3 -0
  731. package/packages/pools/src/reqwest.rs +25 -0
  732. package/packages/runtime/Cargo.lock +1394 -0
  733. package/packages/runtime/Cargo.toml +29 -0
  734. package/packages/runtime/src/lib.rs +154 -0
  735. package/packages/runtime/src/metrics.rs +34 -0
  736. package/packages/runtime/src/term_signal.rs +113 -0
  737. package/packages/runtime/src/traces.rs +158 -0
  738. package/packages/service-manager/Cargo.toml +19 -0
  739. package/packages/service-manager/src/lib.rs +359 -0
  740. package/packages/telemetry/Cargo.toml +13 -0
  741. package/packages/telemetry/README.md +12 -0
  742. package/packages/telemetry/src/lib.rs +39 -0
  743. package/packages/test-deps/Cargo.toml +19 -0
  744. package/packages/test-deps/src/datacenter.rs +109 -0
  745. package/packages/test-deps/src/lib.rs +131 -0
  746. package/packages/test-deps-docker/Cargo.toml +14 -0
  747. package/packages/test-deps-docker/src/database.rs +135 -0
  748. package/packages/test-deps-docker/src/lib.rs +280 -0
  749. package/packages/test-deps-docker/src/pubsub.rs +76 -0
  750. package/packages/tracing-reconfigure/Cargo.toml +18 -0
  751. package/packages/tracing-reconfigure/src/lib.rs +78 -0
  752. package/packages/tracing-utils/Cargo.toml +12 -0
  753. package/packages/tracing-utils/src/lib.rs +91 -0
  754. package/packages/types/Cargo.toml +19 -0
  755. package/packages/types/README.md +3 -0
  756. package/packages/types/src/actors.rs +79 -0
  757. package/packages/types/src/datacenters.rs +10 -0
  758. package/packages/types/src/keys/mod.rs +2 -0
  759. package/packages/types/src/keys/namespace/mod.rs +1 -0
  760. package/packages/types/src/keys/namespace/runner_config.rs +28 -0
  761. package/packages/types/src/keys/pegboard/mod.rs +7 -0
  762. package/packages/types/src/keys/pegboard/ns.rs +109 -0
  763. package/packages/types/src/lib.rs +7 -0
  764. package/packages/types/src/msgs/mod.rs +1 -0
  765. package/packages/types/src/msgs/pegboard.rs +5 -0
  766. package/packages/types/src/namespaces.rs +10 -0
  767. package/packages/types/src/runner_configs.rs +96 -0
  768. package/packages/types/src/runners.rs +24 -0
  769. package/packages/universaldb/Cargo.toml +32 -0
  770. package/packages/universaldb/src/atomic.rs +190 -0
  771. package/packages/universaldb/src/database.rs +56 -0
  772. package/packages/universaldb/src/driver/mod.rs +87 -0
  773. package/packages/universaldb/src/driver/postgres/database.rs +244 -0
  774. package/packages/universaldb/src/driver/postgres/mod.rs +5 -0
  775. package/packages/universaldb/src/driver/postgres/transaction.rs +337 -0
  776. package/packages/universaldb/src/driver/postgres/transaction_task.rs +538 -0
  777. package/packages/universaldb/src/driver/rocksdb/database.rs +129 -0
  778. package/packages/universaldb/src/driver/rocksdb/mod.rs +6 -0
  779. package/packages/universaldb/src/driver/rocksdb/transaction.rs +354 -0
  780. package/packages/universaldb/src/driver/rocksdb/transaction_conflict_tracker.rs +109 -0
  781. package/packages/universaldb/src/driver/rocksdb/transaction_task.rs +526 -0
  782. package/packages/universaldb/src/error.rs +30 -0
  783. package/packages/universaldb/src/key_selector.rs +97 -0
  784. package/packages/universaldb/src/lib.rs +24 -0
  785. package/packages/universaldb/src/metrics.rs +27 -0
  786. package/packages/universaldb/src/options.rs +284 -0
  787. package/packages/universaldb/src/prelude.rs +8 -0
  788. package/packages/universaldb/src/range_option.rs +159 -0
  789. package/packages/universaldb/src/transaction.rs +378 -0
  790. package/packages/universaldb/src/tx_ops.rs +425 -0
  791. package/packages/universaldb/src/utils/cherry_pick.rs +88 -0
  792. package/packages/universaldb/src/utils/codes.rs +9 -0
  793. package/packages/universaldb/src/utils/ext.rs +58 -0
  794. package/packages/universaldb/src/utils/formal_key.rs +23 -0
  795. package/packages/universaldb/src/utils/keys.rs +134 -0
  796. package/packages/universaldb/src/utils/mod.rs +92 -0
  797. package/packages/universaldb/src/utils/subspace.rs +95 -0
  798. package/packages/universaldb/src/value.rs +159 -0
  799. package/packages/universaldb/src/versionstamp.rs +173 -0
  800. package/packages/universaldb/tests/integration.rs +2733 -0
  801. package/packages/universaldb/tests/integration_gas.rs +264 -0
  802. package/packages/universaldb/tests/rocksdb.rs +141 -0
  803. package/packages/universaldb/tests/versionstamp.rs +184 -0
  804. package/packages/universalpubsub/Cargo.toml +38 -0
  805. package/packages/universalpubsub/benches/simple.rs +932 -0
  806. package/packages/universalpubsub/src/chunking.rs +226 -0
  807. package/packages/universalpubsub/src/driver/memory/mod.rs +91 -0
  808. package/packages/universalpubsub/src/driver/mod.rs +58 -0
  809. package/packages/universalpubsub/src/driver/nats/mod.rs +79 -0
  810. package/packages/universalpubsub/src/driver/postgres/mod.rs +443 -0
  811. package/packages/universalpubsub/src/errors.rs +11 -0
  812. package/packages/universalpubsub/src/lib.rs +7 -0
  813. package/packages/universalpubsub/src/pubsub.rs +415 -0
  814. package/packages/universalpubsub/tests/integration.rs +441 -0
  815. package/packages/universalpubsub/tests/reconnect.rs +359 -0
  816. package/packages/util/Cargo.toml +41 -0
  817. package/packages/util/build.rs +13 -0
  818. package/packages/util/src/backoff.rs +109 -0
  819. package/packages/util/src/billing.rs +3 -0
  820. package/packages/util/src/build_meta.rs +33 -0
  821. package/packages/util/src/check.rs +222 -0
  822. package/packages/util/src/duration.rs +77 -0
  823. package/packages/util/src/faker.rs +81 -0
  824. package/packages/util/src/format.rs +185 -0
  825. package/packages/util/src/future.rs +1 -0
  826. package/packages/util/src/geo.rs +5 -0
  827. package/packages/util/src/lib.rs +40 -0
  828. package/packages/util/src/math.rs +35 -0
  829. package/packages/util/src/req.rs +41 -0
  830. package/packages/util/src/serde.rs +516 -0
  831. package/packages/util/src/size.rs +27 -0
  832. package/packages/util/src/sort.rs +13 -0
  833. package/packages/util/src/timestamp.rs +58 -0
  834. package/packages/util/src/url.rs +3 -0
  835. package/packages/util-id/Cargo.toml +13 -0
  836. package/packages/util-id/src/lib.rs +329 -0
  837. package/packages/workflow-worker/Cargo.toml +16 -0
  838. package/packages/workflow-worker/src/lib.rs +15 -0
  839. package/sdks/api/fern/fern.config.json +4 -0
  840. package/sdks/api/fern/generators.yml +25 -0
  841. package/sdks/go/api-full/client/client.go +459 -0
  842. package/sdks/go/api-full/client/client_test.go +43 -0
  843. package/sdks/go/api-full/client/options.go +39 -0
  844. package/sdks/go/api-full/core/client_option.go +44 -0
  845. package/sdks/go/api-full/core/core.go +220 -0
  846. package/sdks/go/api-full/core/core_test.go +219 -0
  847. package/sdks/go/api-full/core/stringer.go +13 -0
  848. package/sdks/go/api-full/datacenters/client.go +50 -0
  849. package/sdks/go/api-full/go.mod +8 -0
  850. package/sdks/go/api-full/go.sum +12 -0
  851. package/sdks/go/api-full/health/client.go +50 -0
  852. package/sdks/go/api-full/namespaces/client.go +92 -0
  853. package/sdks/go/api-full/namespaces.go +15 -0
  854. package/sdks/go/api-full/pointer.go +103 -0
  855. package/sdks/go/api-full/runners/client.go +111 -0
  856. package/sdks/go/api-full/runners.go +18 -0
  857. package/sdks/go/api-full/types.go +1638 -0
  858. package/sdks/rust/api-full/.openapi-generator/FILES +28 -0
  859. package/sdks/rust/api-full/.openapi-generator/VERSION +1 -0
  860. package/sdks/rust/api-full/.openapi-generator-ignore +23 -0
  861. package/sdks/rust/api-full/.travis.yml +1 -0
  862. package/sdks/rust/api-full/Cargo.toml +15 -0
  863. package/sdks/rust/api-full/README.md +53 -0
  864. package/sdks/rust/api-full/docs/Actor.md +19 -0
  865. package/sdks/rust/api-full/docs/ActorLifecycle.md +12 -0
  866. package/sdks/rust/api-full/docs/ActorsApi.md +37 -0
  867. package/sdks/rust/api-full/docs/ActorsCreateRequest.md +13 -0
  868. package/sdks/rust/api-full/docs/ActorsCreateResponse.md +11 -0
  869. package/sdks/rust/api-full/docs/Namespace.md +14 -0
  870. package/sdks/rust/api-full/docs/NamespacesCreateRequest.md +12 -0
  871. package/sdks/rust/api-full/docs/NamespacesCreateResponse.md +11 -0
  872. package/sdks/rust/api-full/docs/NsApi.md +37 -0
  873. package/sdks/rust/api-full/git_push.sh +57 -0
  874. package/sdks/rust/api-full/rust/.openapi-generator/FILES +140 -0
  875. package/sdks/rust/api-full/rust/.openapi-generator/VERSION +1 -0
  876. package/sdks/rust/api-full/rust/.openapi-generator-ignore +23 -0
  877. package/sdks/rust/api-full/rust/.travis.yml +1 -0
  878. package/sdks/rust/api-full/rust/Cargo.toml +15 -0
  879. package/sdks/rust/api-full/rust/README.md +111 -0
  880. package/sdks/rust/api-full/rust/docs/Actor.md +24 -0
  881. package/sdks/rust/api-full/rust/docs/ActorName.md +11 -0
  882. package/sdks/rust/api-full/rust/docs/ActorsCreateApi.md +40 -0
  883. package/sdks/rust/api-full/rust/docs/ActorsCreateRequest.md +16 -0
  884. package/sdks/rust/api-full/rust/docs/ActorsCreateResponse.md +11 -0
  885. package/sdks/rust/api-full/rust/docs/ActorsDeleteApi.md +40 -0
  886. package/sdks/rust/api-full/rust/docs/ActorsGetOrCreateApi.md +40 -0
  887. package/sdks/rust/api-full/rust/docs/ActorsGetOrCreateRequest.md +16 -0
  888. package/sdks/rust/api-full/rust/docs/ActorsGetOrCreateResponse.md +12 -0
  889. package/sdks/rust/api-full/rust/docs/ActorsKvGetApi.md +38 -0
  890. package/sdks/rust/api-full/rust/docs/ActorsKvGetResponse.md +12 -0
  891. package/sdks/rust/api-full/rust/docs/ActorsListApi.md +45 -0
  892. package/sdks/rust/api-full/rust/docs/ActorsListNamesApi.md +41 -0
  893. package/sdks/rust/api-full/rust/docs/ActorsListNamesResponse.md +12 -0
  894. package/sdks/rust/api-full/rust/docs/ActorsListResponse.md +12 -0
  895. package/sdks/rust/api-full/rust/docs/CrashPolicy.md +14 -0
  896. package/sdks/rust/api-full/rust/docs/Datacenter.md +13 -0
  897. package/sdks/rust/api-full/rust/docs/DatacenterHealth.md +16 -0
  898. package/sdks/rust/api-full/rust/docs/DatacentersApi.md +34 -0
  899. package/sdks/rust/api-full/rust/docs/DatacentersListResponse.md +12 -0
  900. package/sdks/rust/api-full/rust/docs/HealthApi.md +34 -0
  901. package/sdks/rust/api-full/rust/docs/HealthFanoutResponse.md +11 -0
  902. package/sdks/rust/api-full/rust/docs/HealthResponse.md +13 -0
  903. package/sdks/rust/api-full/rust/docs/HealthStatus.md +13 -0
  904. package/sdks/rust/api-full/rust/docs/Namespace.md +14 -0
  905. package/sdks/rust/api-full/rust/docs/NamespaceListResponse.md +12 -0
  906. package/sdks/rust/api-full/rust/docs/NamespacesApi.md +69 -0
  907. package/sdks/rust/api-full/rust/docs/NamespacesCreateRequest.md +12 -0
  908. package/sdks/rust/api-full/rust/docs/NamespacesCreateResponse.md +11 -0
  909. package/sdks/rust/api-full/rust/docs/Pagination.md +11 -0
  910. package/sdks/rust/api-full/rust/docs/Runner.md +25 -0
  911. package/sdks/rust/api-full/rust/docs/RunnerConfig.md +13 -0
  912. package/sdks/rust/api-full/rust/docs/RunnerConfigKind.md +12 -0
  913. package/sdks/rust/api-full/rust/docs/RunnerConfigKindOneOf.md +11 -0
  914. package/sdks/rust/api-full/rust/docs/RunnerConfigKindOneOf1.md +11 -0
  915. package/sdks/rust/api-full/rust/docs/RunnerConfigKindOneOf1Serverless.md +17 -0
  916. package/sdks/rust/api-full/rust/docs/RunnerConfigVariant.md +13 -0
  917. package/sdks/rust/api-full/rust/docs/RunnerConfigsDeleteApi.md +38 -0
  918. package/sdks/rust/api-full/rust/docs/RunnerConfigsListApi.md +41 -0
  919. package/sdks/rust/api-full/rust/docs/RunnerConfigsListResponse.md +12 -0
  920. package/sdks/rust/api-full/rust/docs/RunnerConfigsListResponseRunnerConfigsValue.md +11 -0
  921. package/sdks/rust/api-full/rust/docs/RunnerConfigsRefreshMetadataApi.md +39 -0
  922. package/sdks/rust/api-full/rust/docs/RunnerConfigsServerlessHealthCheckApi.md +38 -0
  923. package/sdks/rust/api-full/rust/docs/RunnerConfigsServerlessHealthCheckRequest.md +12 -0
  924. package/sdks/rust/api-full/rust/docs/RunnerConfigsServerlessHealthCheckResponse.md +12 -0
  925. package/sdks/rust/api-full/rust/docs/RunnerConfigsServerlessHealthCheckResponseOneOf.md +11 -0
  926. package/sdks/rust/api-full/rust/docs/RunnerConfigsServerlessHealthCheckResponseOneOf1.md +11 -0
  927. package/sdks/rust/api-full/rust/docs/RunnerConfigsServerlessHealthCheckResponseOneOf1Failure.md +11 -0
  928. package/sdks/rust/api-full/rust/docs/RunnerConfigsServerlessHealthCheckResponseOneOfSuccess.md +11 -0
  929. package/sdks/rust/api-full/rust/docs/RunnerConfigsServerlessMetadataError.md +16 -0
  930. package/sdks/rust/api-full/rust/docs/RunnerConfigsServerlessMetadataErrorOneOf.md +11 -0
  931. package/sdks/rust/api-full/rust/docs/RunnerConfigsServerlessMetadataErrorOneOf1.md +11 -0
  932. package/sdks/rust/api-full/rust/docs/RunnerConfigsServerlessMetadataErrorOneOf2.md +11 -0
  933. package/sdks/rust/api-full/rust/docs/RunnerConfigsServerlessMetadataErrorOneOf3.md +11 -0
  934. package/sdks/rust/api-full/rust/docs/RunnerConfigsServerlessMetadataErrorOneOf3NonSuccessStatus.md +12 -0
  935. package/sdks/rust/api-full/rust/docs/RunnerConfigsServerlessMetadataErrorOneOf4.md +11 -0
  936. package/sdks/rust/api-full/rust/docs/RunnerConfigsServerlessMetadataErrorOneOf4InvalidResponseJson.md +11 -0
  937. package/sdks/rust/api-full/rust/docs/RunnerConfigsServerlessMetadataErrorOneOf5.md +11 -0
  938. package/sdks/rust/api-full/rust/docs/RunnerConfigsServerlessMetadataErrorOneOf5InvalidResponseSchema.md +12 -0
  939. package/sdks/rust/api-full/rust/docs/RunnerConfigsUpsertApi.md +39 -0
  940. package/sdks/rust/api-full/rust/docs/RunnerConfigsUpsertRequestBody.md +11 -0
  941. package/sdks/rust/api-full/rust/docs/RunnerConfigsUpsertResponse.md +11 -0
  942. package/sdks/rust/api-full/rust/docs/RunnersApi.md +75 -0
  943. package/sdks/rust/api-full/rust/docs/RunnersListNamesResponse.md +12 -0
  944. package/sdks/rust/api-full/rust/docs/RunnersListResponse.md +12 -0
  945. package/sdks/rust/api-full/rust/git_push.sh +57 -0
  946. package/sdks/rust/api-full/rust/src/apis/actors_create_api.rs +68 -0
  947. package/sdks/rust/api-full/rust/src/apis/actors_delete_api.rs +69 -0
  948. package/sdks/rust/api-full/rust/src/apis/actors_get_or_create_api.rs +68 -0
  949. package/sdks/rust/api-full/rust/src/apis/actors_kv_get_api.rs +65 -0
  950. package/sdks/rust/api-full/rust/src/apis/actors_list_api.rs +90 -0
  951. package/sdks/rust/api-full/rust/src/apis/actors_list_names_api.rs +74 -0
  952. package/sdks/rust/api-full/rust/src/apis/configuration.rs +51 -0
  953. package/sdks/rust/api-full/rust/src/apis/datacenters_api.rs +62 -0
  954. package/sdks/rust/api-full/rust/src/apis/health_api.rs +62 -0
  955. package/sdks/rust/api-full/rust/src/apis/mod.rs +130 -0
  956. package/sdks/rust/api-full/rust/src/apis/namespaces_api.rs +126 -0
  957. package/sdks/rust/api-full/rust/src/apis/runner_configs_delete_api.rs +66 -0
  958. package/sdks/rust/api-full/rust/src/apis/runner_configs_list_api.rs +81 -0
  959. package/sdks/rust/api-full/rust/src/apis/runner_configs_refresh_metadata_api.rs +68 -0
  960. package/sdks/rust/api-full/rust/src/apis/runner_configs_serverless_health_check_api.rs +67 -0
  961. package/sdks/rust/api-full/rust/src/apis/runner_configs_upsert_api.rs +68 -0
  962. package/sdks/rust/api-full/rust/src/apis/runners_api.rs +141 -0
  963. package/sdks/rust/api-full/rust/src/lib.rs +11 -0
  964. package/sdks/rust/api-full/rust/src/models/actor.rs +73 -0
  965. package/sdks/rust/api-full/rust/src/models/actor_name.rs +27 -0
  966. package/sdks/rust/api-full/rust/src/models/actors_create_request.rs +42 -0
  967. package/sdks/rust/api-full/rust/src/models/actors_create_response.rs +27 -0
  968. package/sdks/rust/api-full/rust/src/models/actors_get_or_create_request.rs +42 -0
  969. package/sdks/rust/api-full/rust/src/models/actors_get_or_create_response.rs +30 -0
  970. package/sdks/rust/api-full/rust/src/models/actors_kv_get_response.rs +30 -0
  971. package/sdks/rust/api-full/rust/src/models/actors_list_names_response.rs +30 -0
  972. package/sdks/rust/api-full/rust/src/models/actors_list_response.rs +30 -0
  973. package/sdks/rust/api-full/rust/src/models/crash_policy.rs +41 -0
  974. package/sdks/rust/api-full/rust/src/models/datacenter.rs +33 -0
  975. package/sdks/rust/api-full/rust/src/models/datacenter_health.rs +42 -0
  976. package/sdks/rust/api-full/rust/src/models/datacenters_list_response.rs +30 -0
  977. package/sdks/rust/api-full/rust/src/models/health_fanout_response.rs +27 -0
  978. package/sdks/rust/api-full/rust/src/models/health_response.rs +33 -0
  979. package/sdks/rust/api-full/rust/src/models/health_status.rs +38 -0
  980. package/sdks/rust/api-full/rust/src/models/mod.rs +100 -0
  981. package/sdks/rust/api-full/rust/src/models/namespace.rs +36 -0
  982. package/sdks/rust/api-full/rust/src/models/namespace_list_response.rs +30 -0
  983. package/sdks/rust/api-full/rust/src/models/namespaces_create_request.rs +30 -0
  984. package/sdks/rust/api-full/rust/src/models/namespaces_create_response.rs +27 -0
  985. package/sdks/rust/api-full/rust/src/models/pagination.rs +27 -0
  986. package/sdks/rust/api-full/rust/src/models/runner.rs +69 -0
  987. package/sdks/rust/api-full/rust/src/models/runner_config.rs +33 -0
  988. package/sdks/rust/api-full/rust/src/models/runner_config_kind.rs +26 -0
  989. package/sdks/rust/api-full/rust/src/models/runner_config_kind_one_of.rs +27 -0
  990. package/sdks/rust/api-full/rust/src/models/runner_config_kind_one_of_1.rs +27 -0
  991. package/sdks/rust/api-full/rust/src/models/runner_config_kind_one_of_1_serverless.rs +46 -0
  992. package/sdks/rust/api-full/rust/src/models/runner_config_variant.rs +38 -0
  993. package/sdks/rust/api-full/rust/src/models/runner_configs_list_response.rs +30 -0
  994. package/sdks/rust/api-full/rust/src/models/runner_configs_list_response_runner_configs_value.rs +27 -0
  995. package/sdks/rust/api-full/rust/src/models/runner_configs_serverless_health_check_request.rs +30 -0
  996. package/sdks/rust/api-full/rust/src/models/runner_configs_serverless_health_check_response.rs +26 -0
  997. package/sdks/rust/api-full/rust/src/models/runner_configs_serverless_health_check_response_one_of.rs +27 -0
  998. package/sdks/rust/api-full/rust/src/models/runner_configs_serverless_health_check_response_one_of_1.rs +27 -0
  999. package/sdks/rust/api-full/rust/src/models/runner_configs_serverless_health_check_response_one_of_1_failure.rs +27 -0
  1000. package/sdks/rust/api-full/rust/src/models/runner_configs_serverless_health_check_response_one_of_success.rs +27 -0
  1001. package/sdks/rust/api-full/rust/src/models/runner_configs_serverless_metadata_error.rs +30 -0
  1002. package/sdks/rust/api-full/rust/src/models/runner_configs_serverless_metadata_error_one_of.rs +27 -0
  1003. package/sdks/rust/api-full/rust/src/models/runner_configs_serverless_metadata_error_one_of_1.rs +27 -0
  1004. package/sdks/rust/api-full/rust/src/models/runner_configs_serverless_metadata_error_one_of_2.rs +27 -0
  1005. package/sdks/rust/api-full/rust/src/models/runner_configs_serverless_metadata_error_one_of_3.rs +27 -0
  1006. package/sdks/rust/api-full/rust/src/models/runner_configs_serverless_metadata_error_one_of_3_non_success_status.rs +30 -0
  1007. package/sdks/rust/api-full/rust/src/models/runner_configs_serverless_metadata_error_one_of_4.rs +27 -0
  1008. package/sdks/rust/api-full/rust/src/models/runner_configs_serverless_metadata_error_one_of_4_invalid_response_json.rs +27 -0
  1009. package/sdks/rust/api-full/rust/src/models/runner_configs_serverless_metadata_error_one_of_5.rs +27 -0
  1010. package/sdks/rust/api-full/rust/src/models/runner_configs_serverless_metadata_error_one_of_5_invalid_response_schema.rs +30 -0
  1011. package/sdks/rust/api-full/rust/src/models/runner_configs_upsert_request_body.rs +27 -0
  1012. package/sdks/rust/api-full/rust/src/models/runner_configs_upsert_response.rs +27 -0
  1013. package/sdks/rust/api-full/rust/src/models/runners_list_names_response.rs +30 -0
  1014. package/sdks/rust/api-full/rust/src/models/runners_list_response.rs +30 -0
  1015. package/sdks/rust/api-full/src/apis/actors_api.rs +67 -0
  1016. package/sdks/rust/api-full/src/apis/configuration.rs +48 -0
  1017. package/sdks/rust/api-full/src/apis/mod.rs +119 -0
  1018. package/sdks/rust/api-full/src/apis/ns_api.rs +67 -0
  1019. package/sdks/rust/api-full/src/lib.rs +11 -0
  1020. package/sdks/rust/api-full/src/models/actor.rs +72 -0
  1021. package/sdks/rust/api-full/src/models/actor_lifecycle.rs +29 -0
  1022. package/sdks/rust/api-full/src/models/actors_create_request.rs +36 -0
  1023. package/sdks/rust/api-full/src/models/actors_create_response.rs +26 -0
  1024. package/sdks/rust/api-full/src/models/mod.rs +14 -0
  1025. package/sdks/rust/api-full/src/models/namespace.rs +40 -0
  1026. package/sdks/rust/api-full/src/models/namespaces_create_request.rs +26 -0
  1027. package/sdks/rust/api-full/src/models/namespaces_create_response.rs +26 -0
  1028. package/sdks/rust/data/Cargo.toml +18 -0
  1029. package/sdks/rust/data/build.rs +15 -0
  1030. package/sdks/rust/data/src/converted.rs +137 -0
  1031. package/sdks/rust/data/src/generated.rs +1 -0
  1032. package/sdks/rust/data/src/lib.rs +11 -0
  1033. package/sdks/rust/data/src/versioned/mod.rs +178 -0
  1034. package/sdks/rust/data/src/versioned/namespace_runner_config.rs +125 -0
  1035. package/sdks/rust/epoxy-protocol/Cargo.toml +17 -0
  1036. package/sdks/rust/epoxy-protocol/build.rs +18 -0
  1037. package/sdks/rust/epoxy-protocol/src/generated.rs +1 -0
  1038. package/sdks/rust/epoxy-protocol/src/lib.rs +7 -0
  1039. package/sdks/rust/epoxy-protocol/src/versioned.rs +206 -0
  1040. package/sdks/rust/runner-protocol/Cargo.toml +23 -0
  1041. package/sdks/rust/runner-protocol/build.rs +115 -0
  1042. package/sdks/rust/runner-protocol/src/compat.rs +7 -0
  1043. package/sdks/rust/runner-protocol/src/generated.rs +1 -0
  1044. package/sdks/rust/runner-protocol/src/lib.rs +10 -0
  1045. package/sdks/rust/runner-protocol/src/util.rs +14 -0
  1046. package/sdks/rust/runner-protocol/src/uuid_compat.rs +209 -0
  1047. package/sdks/rust/runner-protocol/src/versioned.rs +1734 -0
  1048. package/sdks/rust/ups-protocol/Cargo.toml +17 -0
  1049. package/sdks/rust/ups-protocol/build.rs +18 -0
  1050. package/sdks/rust/ups-protocol/src/generated.rs +1 -0
  1051. package/sdks/rust/ups-protocol/src/lib.rs +7 -0
  1052. package/sdks/rust/ups-protocol/src/versioned.rs +48 -0
  1053. package/sdks/schemas/README.md +6 -0
  1054. package/sdks/schemas/data/namespace.runner_config.v1.bare +13 -0
  1055. package/sdks/schemas/data/namespace.runner_config.v2.bare +23 -0
  1056. package/sdks/schemas/data/pegboard.namespace.actor_by_key.v1.bare +6 -0
  1057. package/sdks/schemas/data/pegboard.namespace.actor_name.v1.bare +5 -0
  1058. package/sdks/schemas/data/pegboard.namespace.runner_alloc_idx.v1.bare +7 -0
  1059. package/sdks/schemas/data/pegboard.namespace.runner_by_key.v1.bare +6 -0
  1060. package/sdks/schemas/data/pegboard.runner.metadata.v1.bare +5 -0
  1061. package/sdks/schemas/epoxy-protocol/v1.bare +260 -0
  1062. package/sdks/schemas/runner-protocol/v1.bare +393 -0
  1063. package/sdks/schemas/runner-protocol/v2.bare +403 -0
  1064. package/sdks/schemas/runner-protocol/v3.bare +436 -0
  1065. package/sdks/schemas/ups-protocol/v1.bare +23 -0
  1066. package/sdks/typescript/api-full/.turbo/turbo-build.log +42 -0
  1067. package/sdks/typescript/api-full/build.js +69 -0
  1068. package/sdks/typescript/api-full/package.json +59 -0
  1069. package/sdks/typescript/api-full/rivetkit-engine-api-full-25.5.3.tgz +0 -0
  1070. package/sdks/typescript/api-full/src/Client.ts +984 -0
  1071. package/sdks/typescript/api-full/src/api/client/index.ts +1 -0
  1072. package/sdks/typescript/api-full/src/api/client/requests/ActorsCreateRequest.ts +24 -0
  1073. package/sdks/typescript/api-full/src/api/client/requests/ActorsDeleteRequest.ts +11 -0
  1074. package/sdks/typescript/api-full/src/api/client/requests/ActorsGetOrCreateRequest.ts +25 -0
  1075. package/sdks/typescript/api-full/src/api/client/requests/ActorsListNamesRequest.ts +15 -0
  1076. package/sdks/typescript/api-full/src/api/client/requests/ActorsListRequest.ts +19 -0
  1077. package/sdks/typescript/api-full/src/api/client/requests/RunnerConfigsDeleteRequest.ts +13 -0
  1078. package/sdks/typescript/api-full/src/api/client/requests/RunnerConfigsListRequest.ts +19 -0
  1079. package/sdks/typescript/api-full/src/api/client/requests/RunnerConfigsRefreshMetadataRequest.ts +19 -0
  1080. package/sdks/typescript/api-full/src/api/client/requests/RunnerConfigsServerlessHealthCheckRequest.ts +16 -0
  1081. package/sdks/typescript/api-full/src/api/client/requests/RunnerConfigsUpsertRequestBody.ts +19 -0
  1082. package/sdks/typescript/api-full/src/api/client/requests/index.ts +10 -0
  1083. package/sdks/typescript/api-full/src/api/index.ts +3 -0
  1084. package/sdks/typescript/api-full/src/api/resources/datacenters/client/Client.ts +97 -0
  1085. package/sdks/typescript/api-full/src/api/resources/datacenters/client/index.ts +1 -0
  1086. package/sdks/typescript/api-full/src/api/resources/datacenters/index.ts +1 -0
  1087. package/sdks/typescript/api-full/src/api/resources/health/client/Client.ts +97 -0
  1088. package/sdks/typescript/api-full/src/api/resources/health/client/index.ts +1 -0
  1089. package/sdks/typescript/api-full/src/api/resources/health/index.ts +1 -0
  1090. package/sdks/typescript/api-full/src/api/resources/index.ts +6 -0
  1091. package/sdks/typescript/api-full/src/api/resources/namespaces/client/Client.ts +187 -0
  1092. package/sdks/typescript/api-full/src/api/resources/namespaces/client/index.ts +1 -0
  1093. package/sdks/typescript/api-full/src/api/resources/namespaces/client/requests/NamespacesCreateRequest.ts +15 -0
  1094. package/sdks/typescript/api-full/src/api/resources/namespaces/client/requests/NamespacesListRequest.ts +14 -0
  1095. package/sdks/typescript/api-full/src/api/resources/namespaces/client/requests/index.ts +2 -0
  1096. package/sdks/typescript/api-full/src/api/resources/namespaces/index.ts +1 -0
  1097. package/sdks/typescript/api-full/src/api/resources/runners/client/Client.ts +209 -0
  1098. package/sdks/typescript/api-full/src/api/resources/runners/client/index.ts +1 -0
  1099. package/sdks/typescript/api-full/src/api/resources/runners/client/requests/RunnersListNamesRequest.ts +15 -0
  1100. package/sdks/typescript/api-full/src/api/resources/runners/client/requests/RunnersListRequest.ts +18 -0
  1101. package/sdks/typescript/api-full/src/api/resources/runners/client/requests/index.ts +2 -0
  1102. package/sdks/typescript/api-full/src/api/resources/runners/index.ts +1 -0
  1103. package/sdks/typescript/api-full/src/api/types/Actor.ts +32 -0
  1104. package/sdks/typescript/api-full/src/api/types/ActorName.ts +7 -0
  1105. package/sdks/typescript/api-full/src/api/types/ActorsCreateResponse.ts +9 -0
  1106. package/sdks/typescript/api-full/src/api/types/ActorsDeleteResponse.ts +5 -0
  1107. package/sdks/typescript/api-full/src/api/types/ActorsGetOrCreateResponse.ts +10 -0
  1108. package/sdks/typescript/api-full/src/api/types/ActorsKvGetResponse.ts +8 -0
  1109. package/sdks/typescript/api-full/src/api/types/ActorsListNamesResponse.ts +10 -0
  1110. package/sdks/typescript/api-full/src/api/types/ActorsListResponse.ts +10 -0
  1111. package/sdks/typescript/api-full/src/api/types/CrashPolicy.ts +10 -0
  1112. package/sdks/typescript/api-full/src/api/types/Datacenter.ts +9 -0
  1113. package/sdks/typescript/api-full/src/api/types/DatacenterHealth.ts +14 -0
  1114. package/sdks/typescript/api-full/src/api/types/DatacentersListResponse.ts +10 -0
  1115. package/sdks/typescript/api-full/src/api/types/HealthFanoutResponse.ts +9 -0
  1116. package/sdks/typescript/api-full/src/api/types/HealthResponse.ts +9 -0
  1117. package/sdks/typescript/api-full/src/api/types/HealthStatus.ts +9 -0
  1118. package/sdks/typescript/api-full/src/api/types/Namespace.ts +12 -0
  1119. package/sdks/typescript/api-full/src/api/types/NamespaceListResponse.ts +10 -0
  1120. package/sdks/typescript/api-full/src/api/types/NamespacesCreateResponse.ts +9 -0
  1121. package/sdks/typescript/api-full/src/api/types/Pagination.ts +7 -0
  1122. package/sdks/typescript/api-full/src/api/types/RivetId.ts +5 -0
  1123. package/sdks/typescript/api-full/src/api/types/Runner.ts +23 -0
  1124. package/sdks/typescript/api-full/src/api/types/RunnerConfig.ts +11 -0
  1125. package/sdks/typescript/api-full/src/api/types/RunnerConfigKind.ts +7 -0
  1126. package/sdks/typescript/api-full/src/api/types/RunnerConfigKindNormal.ts +7 -0
  1127. package/sdks/typescript/api-full/src/api/types/RunnerConfigKindServerless.ts +9 -0
  1128. package/sdks/typescript/api-full/src/api/types/RunnerConfigKindServerlessServerless.ts +14 -0
  1129. package/sdks/typescript/api-full/src/api/types/RunnerConfigServerless.ts +14 -0
  1130. package/sdks/typescript/api-full/src/api/types/RunnerConfigVariant.ts +9 -0
  1131. package/sdks/typescript/api-full/src/api/types/RunnerConfigsDeleteResponse.ts +5 -0
  1132. package/sdks/typescript/api-full/src/api/types/RunnerConfigsListResponse.ts +10 -0
  1133. package/sdks/typescript/api-full/src/api/types/RunnerConfigsListResponseRunnerConfigsValue.ts +9 -0
  1134. package/sdks/typescript/api-full/src/api/types/RunnerConfigsRefreshMetadataRequestBody.ts +5 -0
  1135. package/sdks/typescript/api-full/src/api/types/RunnerConfigsRefreshMetadataResponse.ts +5 -0
  1136. package/sdks/typescript/api-full/src/api/types/RunnerConfigsServerlessHealthCheckResponse.ts +9 -0
  1137. package/sdks/typescript/api-full/src/api/types/RunnerConfigsServerlessHealthCheckResponseFailure.ts +9 -0
  1138. package/sdks/typescript/api-full/src/api/types/RunnerConfigsServerlessHealthCheckResponseFailureFailure.ts +9 -0
  1139. package/sdks/typescript/api-full/src/api/types/RunnerConfigsServerlessHealthCheckResponseSuccess.ts +9 -0
  1140. package/sdks/typescript/api-full/src/api/types/RunnerConfigsServerlessHealthCheckResponseSuccessSuccess.ts +7 -0
  1141. package/sdks/typescript/api-full/src/api/types/RunnerConfigsServerlessMetadataError.ts +13 -0
  1142. package/sdks/typescript/api-full/src/api/types/RunnerConfigsServerlessMetadataErrorInvalidRequest.ts +7 -0
  1143. package/sdks/typescript/api-full/src/api/types/RunnerConfigsServerlessMetadataErrorInvalidResponseJson.ts +9 -0
  1144. package/sdks/typescript/api-full/src/api/types/RunnerConfigsServerlessMetadataErrorInvalidResponseJsonInvalidResponseJson.ts +7 -0
  1145. package/sdks/typescript/api-full/src/api/types/RunnerConfigsServerlessMetadataErrorInvalidResponseSchema.ts +9 -0
  1146. package/sdks/typescript/api-full/src/api/types/RunnerConfigsServerlessMetadataErrorInvalidResponseSchemaInvalidResponseSchema.ts +8 -0
  1147. package/sdks/typescript/api-full/src/api/types/RunnerConfigsServerlessMetadataErrorNonSuccessStatus.ts +9 -0
  1148. package/sdks/typescript/api-full/src/api/types/RunnerConfigsServerlessMetadataErrorNonSuccessStatusNonSuccessStatus.ts +8 -0
  1149. package/sdks/typescript/api-full/src/api/types/RunnerConfigsServerlessMetadataErrorRequestFailed.ts +7 -0
  1150. package/sdks/typescript/api-full/src/api/types/RunnerConfigsServerlessMetadataErrorRequestTimedOut.ts +7 -0
  1151. package/sdks/typescript/api-full/src/api/types/RunnerConfigsUpsertResponse.ts +7 -0
  1152. package/sdks/typescript/api-full/src/api/types/RunnersListNamesResponse.ts +10 -0
  1153. package/sdks/typescript/api-full/src/api/types/RunnersListResponse.ts +10 -0
  1154. package/sdks/typescript/api-full/src/api/types/index.ts +51 -0
  1155. package/sdks/typescript/api-full/src/core/auth/BasicAuth.ts +31 -0
  1156. package/sdks/typescript/api-full/src/core/auth/BearerToken.ts +15 -0
  1157. package/sdks/typescript/api-full/src/core/auth/index.ts +2 -0
  1158. package/sdks/typescript/api-full/src/core/fetcher/APIResponse.ts +12 -0
  1159. package/sdks/typescript/api-full/src/core/fetcher/Fetcher.ts +144 -0
  1160. package/sdks/typescript/api-full/src/core/fetcher/Supplier.ts +11 -0
  1161. package/sdks/typescript/api-full/src/core/fetcher/createRequestUrl.ts +10 -0
  1162. package/sdks/typescript/api-full/src/core/fetcher/getFetchFn.ts +25 -0
  1163. package/sdks/typescript/api-full/src/core/fetcher/getHeader.ts +8 -0
  1164. package/sdks/typescript/api-full/src/core/fetcher/getRequestBody.ts +16 -0
  1165. package/sdks/typescript/api-full/src/core/fetcher/getResponseBody.ts +34 -0
  1166. package/sdks/typescript/api-full/src/core/fetcher/index.ts +5 -0
  1167. package/sdks/typescript/api-full/src/core/fetcher/makeRequest.ts +44 -0
  1168. package/sdks/typescript/api-full/src/core/fetcher/requestWithRetries.ts +33 -0
  1169. package/sdks/typescript/api-full/src/core/fetcher/signals.ts +38 -0
  1170. package/sdks/typescript/api-full/src/core/fetcher/stream-wrappers/Node18UniversalStreamWrapper.ts +257 -0
  1171. package/sdks/typescript/api-full/src/core/fetcher/stream-wrappers/NodePre18StreamWrapper.ts +107 -0
  1172. package/sdks/typescript/api-full/src/core/fetcher/stream-wrappers/UndiciStreamWrapper.ts +243 -0
  1173. package/sdks/typescript/api-full/src/core/fetcher/stream-wrappers/chooseStreamWrapper.ts +34 -0
  1174. package/sdks/typescript/api-full/src/core/index.ts +4 -0
  1175. package/sdks/typescript/api-full/src/core/json.ts +27 -0
  1176. package/sdks/typescript/api-full/src/core/runtime/index.ts +1 -0
  1177. package/sdks/typescript/api-full/src/core/runtime/runtime.ts +131 -0
  1178. package/sdks/typescript/api-full/src/core/schemas/Schema.ts +101 -0
  1179. package/sdks/typescript/api-full/src/core/schemas/builders/bigint/bigint.ts +55 -0
  1180. package/sdks/typescript/api-full/src/core/schemas/builders/bigint/index.ts +1 -0
  1181. package/sdks/typescript/api-full/src/core/schemas/builders/date/date.ts +65 -0
  1182. package/sdks/typescript/api-full/src/core/schemas/builders/date/index.ts +1 -0
  1183. package/sdks/typescript/api-full/src/core/schemas/builders/enum/enum.ts +43 -0
  1184. package/sdks/typescript/api-full/src/core/schemas/builders/enum/index.ts +1 -0
  1185. package/sdks/typescript/api-full/src/core/schemas/builders/index.ts +14 -0
  1186. package/sdks/typescript/api-full/src/core/schemas/builders/lazy/index.ts +3 -0
  1187. package/sdks/typescript/api-full/src/core/schemas/builders/lazy/lazy.ts +32 -0
  1188. package/sdks/typescript/api-full/src/core/schemas/builders/lazy/lazyObject.ts +20 -0
  1189. package/sdks/typescript/api-full/src/core/schemas/builders/list/index.ts +1 -0
  1190. package/sdks/typescript/api-full/src/core/schemas/builders/list/list.ts +73 -0
  1191. package/sdks/typescript/api-full/src/core/schemas/builders/literals/booleanLiteral.ts +29 -0
  1192. package/sdks/typescript/api-full/src/core/schemas/builders/literals/index.ts +2 -0
  1193. package/sdks/typescript/api-full/src/core/schemas/builders/literals/stringLiteral.ts +29 -0
  1194. package/sdks/typescript/api-full/src/core/schemas/builders/object/index.ts +22 -0
  1195. package/sdks/typescript/api-full/src/core/schemas/builders/object/object.ts +366 -0
  1196. package/sdks/typescript/api-full/src/core/schemas/builders/object/objectWithoutOptionalProperties.ts +18 -0
  1197. package/sdks/typescript/api-full/src/core/schemas/builders/object/property.ts +23 -0
  1198. package/sdks/typescript/api-full/src/core/schemas/builders/object/types.ts +58 -0
  1199. package/sdks/typescript/api-full/src/core/schemas/builders/object-like/getObjectLikeUtils.ts +79 -0
  1200. package/sdks/typescript/api-full/src/core/schemas/builders/object-like/index.ts +2 -0
  1201. package/sdks/typescript/api-full/src/core/schemas/builders/object-like/types.ts +11 -0
  1202. package/sdks/typescript/api-full/src/core/schemas/builders/primitives/any.ts +4 -0
  1203. package/sdks/typescript/api-full/src/core/schemas/builders/primitives/boolean.ts +25 -0
  1204. package/sdks/typescript/api-full/src/core/schemas/builders/primitives/index.ts +5 -0
  1205. package/sdks/typescript/api-full/src/core/schemas/builders/primitives/number.ts +25 -0
  1206. package/sdks/typescript/api-full/src/core/schemas/builders/primitives/string.ts +25 -0
  1207. package/sdks/typescript/api-full/src/core/schemas/builders/primitives/unknown.ts +4 -0
  1208. package/sdks/typescript/api-full/src/core/schemas/builders/record/index.ts +2 -0
  1209. package/sdks/typescript/api-full/src/core/schemas/builders/record/record.ts +129 -0
  1210. package/sdks/typescript/api-full/src/core/schemas/builders/record/types.ts +17 -0
  1211. package/sdks/typescript/api-full/src/core/schemas/builders/schema-utils/JsonError.ts +9 -0
  1212. package/sdks/typescript/api-full/src/core/schemas/builders/schema-utils/ParseError.ts +9 -0
  1213. package/sdks/typescript/api-full/src/core/schemas/builders/schema-utils/getSchemaUtils.ts +181 -0
  1214. package/sdks/typescript/api-full/src/core/schemas/builders/schema-utils/index.ts +4 -0
  1215. package/sdks/typescript/api-full/src/core/schemas/builders/schema-utils/stringifyValidationErrors.ts +8 -0
  1216. package/sdks/typescript/api-full/src/core/schemas/builders/set/index.ts +1 -0
  1217. package/sdks/typescript/api-full/src/core/schemas/builders/set/set.ts +43 -0
  1218. package/sdks/typescript/api-full/src/core/schemas/builders/undiscriminated-union/index.ts +6 -0
  1219. package/sdks/typescript/api-full/src/core/schemas/builders/undiscriminated-union/types.ts +10 -0
  1220. package/sdks/typescript/api-full/src/core/schemas/builders/undiscriminated-union/undiscriminatedUnion.ts +60 -0
  1221. package/sdks/typescript/api-full/src/core/schemas/builders/union/discriminant.ts +14 -0
  1222. package/sdks/typescript/api-full/src/core/schemas/builders/union/index.ts +10 -0
  1223. package/sdks/typescript/api-full/src/core/schemas/builders/union/types.ts +26 -0
  1224. package/sdks/typescript/api-full/src/core/schemas/builders/union/union.ts +170 -0
  1225. package/sdks/typescript/api-full/src/core/schemas/index.ts +2 -0
  1226. package/sdks/typescript/api-full/src/core/schemas/utils/MaybePromise.ts +1 -0
  1227. package/sdks/typescript/api-full/src/core/schemas/utils/addQuestionMarksToNullableProperties.ts +9 -0
  1228. package/sdks/typescript/api-full/src/core/schemas/utils/createIdentitySchemaCreator.ts +21 -0
  1229. package/sdks/typescript/api-full/src/core/schemas/utils/entries.ts +3 -0
  1230. package/sdks/typescript/api-full/src/core/schemas/utils/filterObject.ts +13 -0
  1231. package/sdks/typescript/api-full/src/core/schemas/utils/getErrorMessageForIncorrectType.ts +25 -0
  1232. package/sdks/typescript/api-full/src/core/schemas/utils/isPlainObject.ts +17 -0
  1233. package/sdks/typescript/api-full/src/core/schemas/utils/keys.ts +3 -0
  1234. package/sdks/typescript/api-full/src/core/schemas/utils/maybeSkipValidation.ts +38 -0
  1235. package/sdks/typescript/api-full/src/core/schemas/utils/partition.ts +12 -0
  1236. package/sdks/typescript/api-full/src/errors/RivetError.ts +47 -0
  1237. package/sdks/typescript/api-full/src/errors/RivetTimeoutError.ts +10 -0
  1238. package/sdks/typescript/api-full/src/errors/index.ts +2 -0
  1239. package/sdks/typescript/api-full/src/index.ts +4 -0
  1240. package/sdks/typescript/api-full/src/serialization/client/index.ts +1 -0
  1241. package/sdks/typescript/api-full/src/serialization/client/requests/ActorsCreateRequest.ts +31 -0
  1242. package/sdks/typescript/api-full/src/serialization/client/requests/ActorsGetOrCreateRequest.ts +31 -0
  1243. package/sdks/typescript/api-full/src/serialization/client/requests/RunnerConfigsServerlessHealthCheckRequest.ts +22 -0
  1244. package/sdks/typescript/api-full/src/serialization/client/requests/RunnerConfigsUpsertRequestBody.ts +21 -0
  1245. package/sdks/typescript/api-full/src/serialization/client/requests/index.ts +4 -0
  1246. package/sdks/typescript/api-full/src/serialization/index.ts +3 -0
  1247. package/sdks/typescript/api-full/src/serialization/resources/index.ts +2 -0
  1248. package/sdks/typescript/api-full/src/serialization/resources/namespaces/client/index.ts +1 -0
  1249. package/sdks/typescript/api-full/src/serialization/resources/namespaces/client/requests/NamespacesCreateRequest.ts +22 -0
  1250. package/sdks/typescript/api-full/src/serialization/resources/namespaces/client/requests/index.ts +1 -0
  1251. package/sdks/typescript/api-full/src/serialization/resources/namespaces/index.ts +1 -0
  1252. package/sdks/typescript/api-full/src/serialization/types/Actor.ts +45 -0
  1253. package/sdks/typescript/api-full/src/serialization/types/ActorName.ts +18 -0
  1254. package/sdks/typescript/api-full/src/serialization/types/ActorsCreateResponse.ts +21 -0
  1255. package/sdks/typescript/api-full/src/serialization/types/ActorsDeleteResponse.ts +16 -0
  1256. package/sdks/typescript/api-full/src/serialization/types/ActorsGetOrCreateResponse.ts +23 -0
  1257. package/sdks/typescript/api-full/src/serialization/types/ActorsKvGetResponse.ts +22 -0
  1258. package/sdks/typescript/api-full/src/serialization/types/ActorsListNamesResponse.ts +24 -0
  1259. package/sdks/typescript/api-full/src/serialization/types/ActorsListResponse.ts +24 -0
  1260. package/sdks/typescript/api-full/src/serialization/types/CrashPolicy.ts +14 -0
  1261. package/sdks/typescript/api-full/src/serialization/types/Datacenter.ts +22 -0
  1262. package/sdks/typescript/api-full/src/serialization/types/DatacenterHealth.ts +32 -0
  1263. package/sdks/typescript/api-full/src/serialization/types/DatacentersListResponse.ts +24 -0
  1264. package/sdks/typescript/api-full/src/serialization/types/HealthFanoutResponse.ts +21 -0
  1265. package/sdks/typescript/api-full/src/serialization/types/HealthResponse.ts +22 -0
  1266. package/sdks/typescript/api-full/src/serialization/types/HealthStatus.ts +14 -0
  1267. package/sdks/typescript/api-full/src/serialization/types/Namespace.ts +25 -0
  1268. package/sdks/typescript/api-full/src/serialization/types/NamespaceListResponse.ts +24 -0
  1269. package/sdks/typescript/api-full/src/serialization/types/NamespacesCreateResponse.ts +21 -0
  1270. package/sdks/typescript/api-full/src/serialization/types/Pagination.ts +18 -0
  1271. package/sdks/typescript/api-full/src/serialization/types/RivetId.ts +13 -0
  1272. package/sdks/typescript/api-full/src/serialization/types/Runner.ts +46 -0
  1273. package/sdks/typescript/api-full/src/serialization/types/RunnerConfig.ts +23 -0
  1274. package/sdks/typescript/api-full/src/serialization/types/RunnerConfigKind.ts +16 -0
  1275. package/sdks/typescript/api-full/src/serialization/types/RunnerConfigKindNormal.ts +20 -0
  1276. package/sdks/typescript/api-full/src/serialization/types/RunnerConfigKindServerless.ts +21 -0
  1277. package/sdks/typescript/api-full/src/serialization/types/RunnerConfigKindServerlessServerless.ts +32 -0
  1278. package/sdks/typescript/api-full/src/serialization/types/RunnerConfigServerless.ts +32 -0
  1279. package/sdks/typescript/api-full/src/serialization/types/RunnerConfigVariant.ts +16 -0
  1280. package/sdks/typescript/api-full/src/serialization/types/RunnerConfigsDeleteResponse.ts +16 -0
  1281. package/sdks/typescript/api-full/src/serialization/types/RunnerConfigsListResponse.ts +27 -0
  1282. package/sdks/typescript/api-full/src/serialization/types/RunnerConfigsListResponseRunnerConfigsValue.ts +21 -0
  1283. package/sdks/typescript/api-full/src/serialization/types/RunnerConfigsRefreshMetadataRequestBody.ts +16 -0
  1284. package/sdks/typescript/api-full/src/serialization/types/RunnerConfigsRefreshMetadataResponse.ts +16 -0
  1285. package/sdks/typescript/api-full/src/serialization/types/RunnerConfigsServerlessHealthCheckResponse.ts +23 -0
  1286. package/sdks/typescript/api-full/src/serialization/types/RunnerConfigsServerlessHealthCheckResponseFailure.ts +21 -0
  1287. package/sdks/typescript/api-full/src/serialization/types/RunnerConfigsServerlessHealthCheckResponseFailureFailure.ts +21 -0
  1288. package/sdks/typescript/api-full/src/serialization/types/RunnerConfigsServerlessHealthCheckResponseSuccess.ts +21 -0
  1289. package/sdks/typescript/api-full/src/serialization/types/RunnerConfigsServerlessHealthCheckResponseSuccessSuccess.ts +20 -0
  1290. package/sdks/typescript/api-full/src/serialization/types/RunnerConfigsServerlessMetadataError.ts +35 -0
  1291. package/sdks/typescript/api-full/src/serialization/types/RunnerConfigsServerlessMetadataErrorInvalidRequest.ts +23 -0
  1292. package/sdks/typescript/api-full/src/serialization/types/RunnerConfigsServerlessMetadataErrorInvalidResponseJson.ts +24 -0
  1293. package/sdks/typescript/api-full/src/serialization/types/RunnerConfigsServerlessMetadataErrorInvalidResponseJsonInvalidResponseJson.ts +20 -0
  1294. package/sdks/typescript/api-full/src/serialization/types/RunnerConfigsServerlessMetadataErrorInvalidResponseSchema.ts +24 -0
  1295. package/sdks/typescript/api-full/src/serialization/types/RunnerConfigsServerlessMetadataErrorInvalidResponseSchemaInvalidResponseSchema.ts +22 -0
  1296. package/sdks/typescript/api-full/src/serialization/types/RunnerConfigsServerlessMetadataErrorNonSuccessStatus.ts +24 -0
  1297. package/sdks/typescript/api-full/src/serialization/types/RunnerConfigsServerlessMetadataErrorNonSuccessStatusNonSuccessStatus.ts +22 -0
  1298. package/sdks/typescript/api-full/src/serialization/types/RunnerConfigsServerlessMetadataErrorRequestFailed.ts +23 -0
  1299. package/sdks/typescript/api-full/src/serialization/types/RunnerConfigsServerlessMetadataErrorRequestTimedOut.ts +23 -0
  1300. package/sdks/typescript/api-full/src/serialization/types/RunnerConfigsUpsertResponse.ts +20 -0
  1301. package/sdks/typescript/api-full/src/serialization/types/RunnersListNamesResponse.ts +23 -0
  1302. package/sdks/typescript/api-full/src/serialization/types/RunnersListResponse.ts +24 -0
  1303. package/sdks/typescript/api-full/src/serialization/types/index.ts +51 -0
  1304. package/sdks/typescript/api-full/tsconfig.json +24 -0
  1305. package/sdks/typescript/runner/.turbo/turbo-build.log +22 -0
  1306. package/sdks/typescript/runner/benches/actor-lifecycle.bench.ts +190 -0
  1307. package/sdks/typescript/runner/benches/utils.ts +143 -0
  1308. package/sdks/typescript/runner/dist/mod.cjs +2951 -0
  1309. package/sdks/typescript/runner/dist/mod.cjs.map +1 -0
  1310. package/sdks/typescript/runner/dist/mod.d.cts +326 -0
  1311. package/sdks/typescript/runner/dist/mod.d.ts +326 -0
  1312. package/sdks/typescript/runner/dist/mod.js +2951 -0
  1313. package/sdks/typescript/runner/dist/mod.js.map +1 -0
  1314. package/sdks/typescript/runner/node_modules/.bin/pino +21 -0
  1315. package/sdks/typescript/runner/node_modules/.bin/tsc +21 -0
  1316. package/sdks/typescript/runner/node_modules/.bin/tsserver +21 -0
  1317. package/sdks/typescript/runner/node_modules/.bin/tsup +21 -0
  1318. package/sdks/typescript/runner/node_modules/.bin/tsup-node +21 -0
  1319. package/sdks/typescript/runner/node_modules/.bin/tsx +21 -0
  1320. package/sdks/typescript/runner/node_modules/.bin/uuid +21 -0
  1321. package/sdks/typescript/runner/node_modules/.bin/vitest +21 -0
  1322. package/sdks/typescript/runner/package.json +37 -0
  1323. package/sdks/typescript/runner/src/actor.ts +196 -0
  1324. package/sdks/typescript/runner/src/log.ts +11 -0
  1325. package/sdks/typescript/runner/src/mod.ts +1755 -0
  1326. package/sdks/typescript/runner/src/stringify.ts +354 -0
  1327. package/sdks/typescript/runner/src/tunnel.ts +1178 -0
  1328. package/sdks/typescript/runner/src/utils.ts +159 -0
  1329. package/sdks/typescript/runner/src/websocket-tunnel-adapter.ts +567 -0
  1330. package/sdks/typescript/runner/src/websocket.ts +43 -0
  1331. package/sdks/typescript/runner/tests/lifecycle.test.ts +596 -0
  1332. package/sdks/typescript/runner/tests/utils.test.ts +194 -0
  1333. package/sdks/typescript/runner/tsconfig.json +11 -0
  1334. package/sdks/typescript/runner/tsup.config.ts +4 -0
  1335. package/sdks/typescript/runner/turbo.json +4 -0
  1336. package/sdks/typescript/runner/vitest.config.ts +16 -0
  1337. package/sdks/typescript/runner-protocol/.turbo/turbo-build.log +22 -0
  1338. package/sdks/typescript/runner-protocol/dist/index.cjs +1632 -0
  1339. package/sdks/typescript/runner-protocol/dist/index.cjs.map +1 -0
  1340. package/sdks/typescript/runner-protocol/dist/index.d.cts +666 -0
  1341. package/sdks/typescript/runner-protocol/dist/index.d.ts +666 -0
  1342. package/sdks/typescript/runner-protocol/dist/index.js +1632 -0
  1343. package/sdks/typescript/runner-protocol/dist/index.js.map +1 -0
  1344. package/sdks/typescript/runner-protocol/node_modules/.bin/tsc +21 -0
  1345. package/sdks/typescript/runner-protocol/node_modules/.bin/tsserver +21 -0
  1346. package/sdks/typescript/runner-protocol/node_modules/.bin/tsup +21 -0
  1347. package/sdks/typescript/runner-protocol/node_modules/.bin/tsup-node +21 -0
  1348. package/sdks/typescript/runner-protocol/package.json +34 -0
  1349. package/sdks/typescript/runner-protocol/src/index.ts +2121 -0
  1350. package/sdks/typescript/runner-protocol/tsconfig.json +17 -0
  1351. package/sdks/typescript/runner-protocol/tsup.config.ts +4 -0
  1352. package/sdks/typescript/runner-protocol/turbo.json +4 -0
  1353. package/sdks/typescript/test-runner/.turbo/turbo-build.log +17 -0
  1354. package/sdks/typescript/test-runner/Dockerfile +26 -0
  1355. package/sdks/typescript/test-runner/dist/index.d.ts +6 -0
  1356. package/sdks/typescript/test-runner/dist/index.js +345 -0
  1357. package/sdks/typescript/test-runner/dist/index.js.map +1 -0
  1358. package/sdks/typescript/test-runner/node_modules/.bin/pino +21 -0
  1359. package/sdks/typescript/test-runner/node_modules/.bin/tsc +21 -0
  1360. package/sdks/typescript/test-runner/node_modules/.bin/tsserver +21 -0
  1361. package/sdks/typescript/test-runner/node_modules/.bin/tsup +21 -0
  1362. package/sdks/typescript/test-runner/node_modules/.bin/tsup-node +21 -0
  1363. package/sdks/typescript/test-runner/node_modules/.bin/tsx +21 -0
  1364. package/sdks/typescript/test-runner/node_modules/.bin/vitest +21 -0
  1365. package/sdks/typescript/test-runner/package.json +27 -0
  1366. package/sdks/typescript/test-runner/src/index.ts +287 -0
  1367. package/sdks/typescript/test-runner/src/log.ts +194 -0
  1368. package/sdks/typescript/test-runner/tsconfig.json +11 -0
  1369. package/sdks/typescript/test-runner/tsup.config.ts +7 -0
  1370. package/sdks/typescript/test-runner/turbo.json +4 -0
  1371. package/sdks/typescript/test-runner/vitest.config.ts +16 -0
  1372. package/tests/load/README.md +28 -0
  1373. package/tests/load/actor-lifecycle/README.md +26 -0
  1374. package/tests/load/actor-lifecycle/actor.ts +41 -0
  1375. package/tests/load/actor-lifecycle/config.ts +14 -0
  1376. package/tests/load/actor-lifecycle/index.ts +62 -0
  1377. package/tests/load/actor-lifecycle/rivet_api.ts +140 -0
  1378. package/tests/load/actor-lifecycle/types.ts +17 -0
  1379. package/tests/load/node_modules/.bin/biome +21 -0
  1380. package/tests/load/node_modules/.bin/tsc +21 -0
  1381. package/tests/load/node_modules/.bin/tsserver +21 -0
  1382. package/tests/load/package.json +15 -0
  1383. package/tests/load/tsconfig.json +20 -0
  1384. package/tests/smoke/README.md +32 -0
  1385. package/tests/smoke/package.json +19 -0
  1386. package/tests/smoke/scripts/connect.ts +41 -0
  1387. package/tests/smoke/src/server/registry.ts +32 -0
  1388. package/tests/smoke/src/server/server.ts +7 -0
  1389. package/tests/smoke/src/smoke-test/index.ts +161 -0
  1390. package/tests/smoke/src/smoke-test/spawn-actor.ts +109 -0
  1391. package/tests/smoke/tsconfig.json +43 -0
  1392. package/tests/smoke/turbo.json +4 -0
@@ -0,0 +1,2699 @@
1
+ use anyhow::{Context, Result, bail, ensure};
2
+ use bytes::Bytes;
3
+ use futures_util::{SinkExt, StreamExt};
4
+ use http_body_util::{BodyExt, Full};
5
+ use hyper::{Request, Response, StatusCode, body::Incoming as BodyIncoming, header::HeaderName};
6
+ use hyper_tungstenite;
7
+ use hyper_util::{client::legacy::Client, rt::TokioExecutor};
8
+ use moka::future::Cache;
9
+ use rand;
10
+ use rivet_api_builder::{ErrorResponse, RawErrorResponse};
11
+ use rivet_api_builder::{RequestIds, X_RIVET_RAY_ID};
12
+ use rivet_error::{INTERNAL_ERROR, RivetError};
13
+ use rivet_metrics::KeyValue;
14
+ use rivet_util::Id;
15
+ use serde_json;
16
+
17
+ use rivet_runner_protocol as protocol;
18
+ use std::{
19
+ borrow::Cow,
20
+ collections::{HashMap as StdHashMap, HashSet},
21
+ net::SocketAddr,
22
+ sync::Arc,
23
+ time::{Duration, Instant},
24
+ };
25
+ use tokio::sync::Mutex;
26
+ use tokio::time::timeout;
27
+ use tokio_tungstenite::tungstenite::{
28
+ client::IntoClientRequest,
29
+ protocol::{CloseFrame, frame::coding::CloseCode},
30
+ };
31
+ use tracing::Instrument;
32
+ use url::Url;
33
+
34
+ use crate::{
35
+ WebSocketHandle,
36
+ custom_serve::{CustomServeTrait, HibernationResult},
37
+ errors, metrics,
38
+ request_context::RequestContext,
39
+ task_group::TaskGroup,
40
+ };
41
+
42
+ const X_RIVET_TARGET: HeaderName = HeaderName::from_static("x-rivet-target");
43
+ const X_RIVET_ACTOR: HeaderName = HeaderName::from_static("x-rivet-actor");
44
+ const X_RIVET_TOKEN: HeaderName = HeaderName::from_static("x-rivet-token");
45
+ pub const X_FORWARDED_FOR: HeaderName = HeaderName::from_static("x-forwarded-for");
46
+ pub const X_RIVET_ERROR: HeaderName = HeaderName::from_static("x-rivet-error");
47
+
48
+ const ROUTE_CACHE_TTL: Duration = Duration::from_secs(60 * 10); // 10 minutes
49
+ const PROXY_STATE_CACHE_TTL: Duration = Duration::from_secs(60 * 60); // 1 hour
50
+ const WEBSOCKET_CLOSE_LINGER: Duration = Duration::from_millis(100); // Keep TCP connection open briefly after WebSocket close
51
+
52
+ /// Response body type that can handle both streaming and buffered responses
53
+ #[derive(Debug)]
54
+ pub enum ResponseBody {
55
+ /// Buffered response body
56
+ Full(Full<Bytes>),
57
+ /// Streaming response body
58
+ Incoming(BodyIncoming),
59
+ }
60
+
61
+ impl http_body::Body for ResponseBody {
62
+ type Data = Bytes;
63
+ type Error = Box<dyn std::error::Error + Send + Sync>;
64
+
65
+ fn poll_frame(
66
+ self: std::pin::Pin<&mut Self>,
67
+ cx: &mut std::task::Context<'_>,
68
+ ) -> std::task::Poll<Option<Result<http_body::Frame<Self::Data>, Self::Error>>> {
69
+ match self.get_mut() {
70
+ ResponseBody::Full(body) => {
71
+ let pin = std::pin::Pin::new(body);
72
+ match pin.poll_frame(cx) {
73
+ std::task::Poll::Ready(Some(Ok(frame))) => {
74
+ std::task::Poll::Ready(Some(Ok(frame)))
75
+ }
76
+ std::task::Poll::Ready(Some(Err(e))) => {
77
+ std::task::Poll::Ready(Some(Err(Box::new(e))))
78
+ }
79
+ std::task::Poll::Ready(None) => std::task::Poll::Ready(None),
80
+ std::task::Poll::Pending => std::task::Poll::Pending,
81
+ }
82
+ }
83
+ ResponseBody::Incoming(body) => {
84
+ let pin = std::pin::Pin::new(body);
85
+ match pin.poll_frame(cx) {
86
+ std::task::Poll::Ready(Some(Ok(frame))) => {
87
+ std::task::Poll::Ready(Some(Ok(frame)))
88
+ }
89
+ std::task::Poll::Ready(Some(Err(e))) => {
90
+ std::task::Poll::Ready(Some(Err(Box::new(e))))
91
+ }
92
+ std::task::Poll::Ready(None) => std::task::Poll::Ready(None),
93
+ std::task::Poll::Pending => std::task::Poll::Pending,
94
+ }
95
+ }
96
+ }
97
+ }
98
+
99
+ fn is_end_stream(&self) -> bool {
100
+ match self {
101
+ ResponseBody::Full(body) => body.is_end_stream(),
102
+ ResponseBody::Incoming(body) => body.is_end_stream(),
103
+ }
104
+ }
105
+
106
+ fn size_hint(&self) -> http_body::SizeHint {
107
+ match self {
108
+ ResponseBody::Full(body) => body.size_hint(),
109
+ ResponseBody::Incoming(body) => body.size_hint(),
110
+ }
111
+ }
112
+ }
113
+
114
+ // Routing types
115
+ #[derive(Clone, Debug)]
116
+ pub struct RouteTarget {
117
+ pub actor_id: Option<Id>,
118
+ pub host: String,
119
+ pub port: u16,
120
+ pub path: String,
121
+ }
122
+
123
+ #[derive(Clone, Debug)]
124
+ pub struct RoutingTimeout {
125
+ pub routing_timeout: u64, // in seconds
126
+ }
127
+
128
+ #[derive(Clone, Debug)]
129
+ pub struct RouteConfig {
130
+ pub targets: Vec<RouteTarget>,
131
+ pub timeout: RoutingTimeout,
132
+ }
133
+
134
+ #[derive(Clone)]
135
+ pub enum RoutingOutput {
136
+ /// Return the data to route to.
137
+ Route(RouteConfig),
138
+ /// Return a custom response.
139
+ Response(StructuredResponse),
140
+ /// Return a custom serve handler.
141
+ CustomServe(Arc<dyn CustomServeTrait>),
142
+ }
143
+
144
+ #[derive(Clone, Debug)]
145
+ pub struct StructuredResponse {
146
+ pub status: StatusCode,
147
+ pub message: Cow<'static, str>,
148
+ pub docs: Option<Cow<'static, str>>,
149
+ }
150
+
151
+ impl StructuredResponse {
152
+ pub fn build_response(&self) -> Result<Response<ResponseBody>> {
153
+ let mut body = StdHashMap::new();
154
+ body.insert("message", self.message.clone().into_owned());
155
+
156
+ if let Some(docs) = &self.docs {
157
+ body.insert("docs", docs.clone().into_owned());
158
+ }
159
+
160
+ let body_json = serde_json::to_string(&body)?;
161
+ let bytes = Bytes::from(body_json);
162
+
163
+ let response = Response::builder()
164
+ .status(self.status)
165
+ .header(hyper::header::CONTENT_TYPE, "application/json")
166
+ .body(ResponseBody::Full(Full::new(bytes)))?;
167
+
168
+ Ok(response)
169
+ }
170
+ }
171
+
172
+ #[derive(Clone)]
173
+ enum ResolveRouteOutput {
174
+ Target(RouteTarget),
175
+ Response(StructuredResponse),
176
+ CustomServe(Arc<dyn CustomServeTrait>),
177
+ }
178
+
179
+ /// Enum defining the type of port the request came in on
180
+ #[derive(Clone, Debug, PartialEq)]
181
+ pub enum PortType {
182
+ Http,
183
+ Https,
184
+ }
185
+
186
+ pub type RoutingFn = Arc<
187
+ dyn for<'a> Fn(
188
+ &'a str,
189
+ &'a str,
190
+ PortType,
191
+ &'a hyper::HeaderMap,
192
+ ) -> futures::future::BoxFuture<'a, Result<RoutingOutput>>
193
+ + Send
194
+ + Sync,
195
+ >;
196
+
197
+ pub type CacheKeyFn = Arc<
198
+ dyn for<'a> Fn(
199
+ &'a str,
200
+ &'a str,
201
+ &'a hyper::Method,
202
+ PortType,
203
+ &'a hyper::HeaderMap,
204
+ ) -> Result<u64>
205
+ + Send
206
+ + Sync,
207
+ >;
208
+
209
+ #[derive(Clone, Debug)]
210
+ pub struct MiddlewareConfig {
211
+ pub rate_limit: RateLimitConfig,
212
+ pub max_in_flight: MaxInFlightConfig,
213
+ pub retry: RetryConfig,
214
+ pub timeout: TimeoutConfig,
215
+ }
216
+
217
+ #[derive(Clone, Debug)]
218
+ pub struct RateLimitConfig {
219
+ pub requests: u64,
220
+ pub period: u64, // in seconds
221
+ }
222
+
223
+ #[derive(Clone, Debug)]
224
+ pub struct MaxInFlightConfig {
225
+ pub amount: usize,
226
+ }
227
+
228
+ #[derive(Clone, Debug)]
229
+ pub struct RetryConfig {
230
+ pub max_attempts: u32,
231
+ pub initial_interval: u64, // in milliseconds
232
+ }
233
+
234
+ #[derive(Clone, Debug)]
235
+ pub struct TimeoutConfig {
236
+ pub request_timeout: u64, // in seconds
237
+ }
238
+
239
+ #[derive(Clone, Debug)]
240
+ pub enum MiddlewareResponse {
241
+ Ok(MiddlewareConfig),
242
+ NotFound,
243
+ }
244
+
245
+ pub type MiddlewareFn = Arc<
246
+ dyn for<'a> Fn(
247
+ &'a Id,
248
+ &'a hyper::HeaderMap,
249
+ ) -> futures::future::BoxFuture<'a, Result<MiddlewareResponse>>
250
+ + Send
251
+ + Sync,
252
+ >;
253
+
254
+ // Cache for routing results
255
+ struct RouteCache {
256
+ cache: Cache<u64, RouteConfig>,
257
+ }
258
+
259
+ impl RouteCache {
260
+ fn new() -> Self {
261
+ Self {
262
+ cache: Cache::builder()
263
+ .max_capacity(10_000)
264
+ .time_to_live(ROUTE_CACHE_TTL)
265
+ .build(),
266
+ }
267
+ }
268
+
269
+ #[tracing::instrument(skip_all)]
270
+ async fn get(&self, key: &u64) -> Option<RouteConfig> {
271
+ self.cache.get(key).await
272
+ }
273
+
274
+ #[tracing::instrument(skip_all)]
275
+ async fn insert(&self, key: u64, result: RouteConfig) {
276
+ self.cache.insert(key, result).await;
277
+
278
+ metrics::ROUTE_CACHE_COUNT.record(self.cache.entry_count(), &[]);
279
+ }
280
+ }
281
+
282
+ // Rate limiter
283
+ struct RateLimiter {
284
+ requests_remaining: u64,
285
+ reset_time: Instant,
286
+ requests_limit: u64,
287
+ period: Duration,
288
+ }
289
+
290
+ impl RateLimiter {
291
+ fn new(requests: u64, period_seconds: u64) -> Self {
292
+ Self {
293
+ requests_remaining: requests,
294
+ reset_time: Instant::now() + Duration::from_secs(period_seconds),
295
+ requests_limit: requests,
296
+ period: Duration::from_secs(period_seconds),
297
+ }
298
+ }
299
+
300
+ fn try_acquire(&mut self) -> bool {
301
+ let now = Instant::now();
302
+
303
+ // Check if we need to reset the counter
304
+ if now >= self.reset_time {
305
+ self.requests_remaining = self.requests_limit;
306
+ self.reset_time = now + self.period;
307
+ }
308
+
309
+ // Try to consume a request
310
+ if self.requests_remaining > 0 {
311
+ self.requests_remaining -= 1;
312
+ true
313
+ } else {
314
+ false
315
+ }
316
+ }
317
+ }
318
+
319
+ // In-flight requests counter
320
+ struct InFlightCounter {
321
+ count: usize,
322
+ max: usize,
323
+ }
324
+
325
+ impl InFlightCounter {
326
+ fn new(max: usize) -> Self {
327
+ Self { count: 0, max }
328
+ }
329
+
330
+ fn try_acquire(&mut self) -> bool {
331
+ if self.count < self.max {
332
+ self.count += 1;
333
+ true
334
+ } else {
335
+ false
336
+ }
337
+ }
338
+
339
+ fn release(&mut self) {
340
+ self.count = self.count.saturating_sub(1);
341
+ }
342
+ }
343
+
344
+ // State shared across all request handlers
345
+ pub struct ProxyState {
346
+ config: rivet_config::Config,
347
+ routing_fn: RoutingFn,
348
+ cache_key_fn: CacheKeyFn,
349
+ middleware_fn: MiddlewareFn,
350
+ route_cache: RouteCache,
351
+ rate_limiters: Cache<(Id, std::net::IpAddr), Arc<Mutex<RateLimiter>>>,
352
+ in_flight_counters: Cache<(Id, std::net::IpAddr), Arc<Mutex<InFlightCounter>>>,
353
+ in_flight_requests: Arc<Mutex<HashSet<protocol::RequestId>>>,
354
+ port_type: PortType,
355
+ clickhouse_inserter: Option<clickhouse_inserter::ClickHouseInserterHandle>,
356
+ tasks: Arc<TaskGroup>,
357
+ }
358
+
359
+ impl ProxyState {
360
+ pub fn new(
361
+ config: rivet_config::Config,
362
+ routing_fn: RoutingFn,
363
+ cache_key_fn: CacheKeyFn,
364
+ middleware_fn: MiddlewareFn,
365
+ port_type: PortType,
366
+ clickhouse_inserter: Option<clickhouse_inserter::ClickHouseInserterHandle>,
367
+ ) -> Self {
368
+ Self {
369
+ config,
370
+ routing_fn,
371
+ cache_key_fn,
372
+ middleware_fn,
373
+ route_cache: RouteCache::new(),
374
+ rate_limiters: Cache::builder()
375
+ .max_capacity(10_000)
376
+ .time_to_live(PROXY_STATE_CACHE_TTL)
377
+ .build(),
378
+ in_flight_counters: Cache::builder()
379
+ .max_capacity(10_000)
380
+ .time_to_live(PROXY_STATE_CACHE_TTL)
381
+ .build(),
382
+ in_flight_requests: Arc::new(Mutex::new(HashSet::new())),
383
+ port_type,
384
+ clickhouse_inserter,
385
+ tasks: TaskGroup::new(),
386
+ }
387
+ }
388
+
389
+ #[tracing::instrument(skip(self))]
390
+ async fn resolve_route(
391
+ &self,
392
+ hostname: &str,
393
+ path: &str,
394
+ method: &hyper::Method,
395
+ port_type: PortType,
396
+ headers: &hyper::HeaderMap,
397
+ ignore_cache: bool,
398
+ ) -> Result<ResolveRouteOutput> {
399
+ // Extract just the hostname, stripping the port if present
400
+ let hostname_only = hostname.split(':').next().unwrap_or(hostname);
401
+
402
+ tracing::debug!(
403
+ hostname = %hostname_only,
404
+ path = %path,
405
+ method = %method,
406
+ port_type = ?port_type,
407
+ "Resolving route for request"
408
+ );
409
+
410
+ let cache_key =
411
+ (self.cache_key_fn)(hostname_only, &path, method, port_type.clone(), headers)?;
412
+
413
+ // Check cache first
414
+ if !ignore_cache {
415
+ if let Some(result) = self.route_cache.get(&cache_key).await {
416
+ // Choose a random target from the cached targets
417
+ if let Some(target) = choose_random_target(&result.targets) {
418
+ return Ok(ResolveRouteOutput::Target(target.clone()));
419
+ }
420
+ }
421
+ }
422
+
423
+ // Not in cache, call routing function with a default timeout
424
+ // Default 15 seconds, routing functions should have their own internal timeouts that are shorter
425
+ let default_timeout = Duration::from_secs(15);
426
+
427
+ tracing::debug!(
428
+ hostname = %hostname_only,
429
+ path = %path,
430
+ cache_hit = false,
431
+ timeout_seconds = default_timeout.as_secs(),
432
+ "Cache miss, calling routing function"
433
+ );
434
+
435
+ let res = timeout(
436
+ default_timeout,
437
+ (self.routing_fn)(hostname_only, path, port_type, headers),
438
+ )
439
+ .await
440
+ .map_err(|_| {
441
+ errors::RequestTimeout {
442
+ timeout_seconds: default_timeout.as_secs(),
443
+ }
444
+ .build()
445
+ })?;
446
+
447
+ match res? {
448
+ RoutingOutput::Route(result) => {
449
+ tracing::debug!(
450
+ hostname = %hostname_only,
451
+ path = %path,
452
+ targets_count = result.targets.len(),
453
+ timeout_secs = result.timeout.routing_timeout,
454
+ "Received routing result"
455
+ );
456
+
457
+ // Cache the result
458
+ self.route_cache.insert(cache_key, result.clone()).await;
459
+ tracing::debug!("Added route to cache");
460
+
461
+ // Choose a random target
462
+ if let Some(target) = choose_random_target(&result.targets) {
463
+ tracing::debug!(
464
+ hostname = %hostname_only,
465
+ path = %path,
466
+ target_host = %target.host,
467
+ target_port = target.port,
468
+ target_path = %target.path,
469
+ actor_id = ?target.actor_id,
470
+ "Selected target for request"
471
+ );
472
+ Ok(ResolveRouteOutput::Target(target.clone()))
473
+ } else {
474
+ tracing::warn!(
475
+ hostname = %hostname_only,
476
+ path = %path,
477
+ "No route targets available from result"
478
+ );
479
+ Err(errors::NoRouteTargets.build())
480
+ }
481
+ }
482
+ RoutingOutput::Response(response) => {
483
+ tracing::debug!(
484
+ hostname = %hostname_only,
485
+ path = %path,
486
+ status = ?response.status,
487
+ "Routing returned custom response"
488
+ );
489
+ Ok(ResolveRouteOutput::Response(response))
490
+ }
491
+ RoutingOutput::CustomServe(handler) => {
492
+ tracing::debug!(
493
+ hostname = %hostname_only,
494
+ path = %path,
495
+ "Routing returned custom serve handler"
496
+ );
497
+ Ok(ResolveRouteOutput::CustomServe(handler))
498
+ }
499
+ }
500
+ }
501
+
502
+ #[tracing::instrument(skip_all)]
503
+ async fn get_middleware_config(
504
+ &self,
505
+ actor_id: &Id,
506
+ headers: &hyper::HeaderMap,
507
+ ) -> Result<MiddlewareConfig> {
508
+ // Call the middleware function with a timeout
509
+ let default_timeout = Duration::from_secs(5); // Default 5 seconds
510
+
511
+ let middleware_result =
512
+ timeout(default_timeout, (self.middleware_fn)(actor_id, headers)).await;
513
+
514
+ match middleware_result {
515
+ Ok(result) => match result? {
516
+ MiddlewareResponse::Ok(config) => Ok(config),
517
+ MiddlewareResponse::NotFound => {
518
+ // Default values if middleware not found for this actor
519
+ Ok(MiddlewareConfig {
520
+ rate_limit: RateLimitConfig {
521
+ requests: 100, // 100 requests
522
+ period: 60, // per 60 seconds
523
+ },
524
+ max_in_flight: MaxInFlightConfig {
525
+ amount: 20, // 20 concurrent requests
526
+ },
527
+ retry: RetryConfig {
528
+ max_attempts: 3, // 3 retry attempts
529
+ initial_interval: 100, // 100ms initial interval
530
+ },
531
+ timeout: TimeoutConfig {
532
+ request_timeout: 30, // 30 seconds for requests
533
+ },
534
+ })
535
+ }
536
+ },
537
+ Err(_) => {
538
+ // Default values if middleware times out
539
+ Ok(MiddlewareConfig {
540
+ rate_limit: RateLimitConfig {
541
+ requests: 100, // 100 requests
542
+ period: 60, // per 60 seconds
543
+ },
544
+ max_in_flight: MaxInFlightConfig {
545
+ amount: 20, // 20 concurrent requests
546
+ },
547
+ retry: RetryConfig {
548
+ max_attempts: 3, // 3 retry attempts
549
+ initial_interval: 100, // 100ms initial interval
550
+ },
551
+ timeout: TimeoutConfig {
552
+ request_timeout: 30, // 30 seconds for requests
553
+ },
554
+ })
555
+ }
556
+ }
557
+ }
558
+
559
+ #[tracing::instrument(skip_all)]
560
+ async fn check_rate_limit(
561
+ &self,
562
+ ip_addr: std::net::IpAddr,
563
+ actor_id: &Option<Id>,
564
+ headers: &hyper::HeaderMap,
565
+ ) -> Result<bool> {
566
+ let Some(actor_id) = *actor_id else {
567
+ // No rate limiting when actor_id is None
568
+ return Ok(true);
569
+ };
570
+
571
+ // Get actor-specific middleware config
572
+ let middleware_config = self.get_middleware_config(&actor_id, headers).await?;
573
+
574
+ let cache_key = (actor_id, ip_addr);
575
+
576
+ // Get existing limiter or create a new one
577
+ let limiter_arc = if let Some(existing_limiter) = self.rate_limiters.get(&cache_key).await {
578
+ existing_limiter
579
+ } else {
580
+ let new_limiter = Arc::new(Mutex::new(RateLimiter::new(
581
+ middleware_config.rate_limit.requests,
582
+ middleware_config.rate_limit.period,
583
+ )));
584
+ self.rate_limiters
585
+ .insert(cache_key, new_limiter.clone())
586
+ .await;
587
+ metrics::RATE_LIMITER_COUNT.record(self.rate_limiters.entry_count(), &[]);
588
+ new_limiter
589
+ };
590
+
591
+ // Try to acquire from the limiter
592
+ let result = {
593
+ let mut limiter = limiter_arc.lock().await;
594
+ limiter.try_acquire()
595
+ };
596
+
597
+ Ok(result)
598
+ }
599
+
600
+ #[tracing::instrument(skip_all)]
601
+ async fn acquire_in_flight(
602
+ &self,
603
+ ip_addr: std::net::IpAddr,
604
+ actor_id: &Option<Id>,
605
+ headers: &hyper::HeaderMap,
606
+ ) -> Result<Option<protocol::RequestId>> {
607
+ // Check in-flight limit if actor_id is present
608
+ if let Some(actor_id) = *actor_id {
609
+ // Get actor-specific middleware config
610
+ let middleware_config = self.get_middleware_config(&actor_id, headers).await?;
611
+
612
+ let cache_key = (actor_id, ip_addr);
613
+
614
+ // Get existing counter or create a new one
615
+ let counter_arc = if let Some(existing_counter) =
616
+ self.in_flight_counters.get(&cache_key).await
617
+ {
618
+ existing_counter
619
+ } else {
620
+ let new_counter = Arc::new(Mutex::new(InFlightCounter::new(
621
+ middleware_config.max_in_flight.amount,
622
+ )));
623
+ self.in_flight_counters
624
+ .insert(cache_key, new_counter.clone())
625
+ .await;
626
+ metrics::IN_FLIGHT_COUNTER_COUNT.record(self.in_flight_counters.entry_count(), &[]);
627
+ new_counter
628
+ };
629
+
630
+ // Try to acquire from the counter
631
+ let acquired = {
632
+ let mut counter = counter_arc.lock().await;
633
+ counter.try_acquire()
634
+ };
635
+
636
+ if !acquired {
637
+ return Ok(None); // Rate limited
638
+ }
639
+ }
640
+
641
+ // Generate unique request ID
642
+ let request_id = Some(self.generate_unique_request_id().await?);
643
+ Ok(request_id)
644
+ }
645
+
646
+ #[tracing::instrument(skip_all)]
647
+ async fn release_in_flight(
648
+ &self,
649
+ ip_addr: std::net::IpAddr,
650
+ actor_id: &Option<Id>,
651
+ request_id: protocol::RequestId,
652
+ ) {
653
+ // Release in-flight counter if actor_id is present
654
+ if let Some(actor_id) = *actor_id {
655
+ let cache_key = (actor_id, ip_addr);
656
+ if let Some(counter_arc) = self.in_flight_counters.get(&cache_key).await {
657
+ let mut counter = counter_arc.lock().await;
658
+ counter.release();
659
+ }
660
+ }
661
+
662
+ // Release request ID
663
+ let mut requests = self.in_flight_requests.lock().await;
664
+ requests.remove(&request_id);
665
+ }
666
+
667
+ /// Generate a unique request ID that is not currently in flight
668
+ async fn generate_unique_request_id(&self) -> Result<protocol::RequestId> {
669
+ const MAX_TRIES: u32 = 100;
670
+ let mut requests = self.in_flight_requests.lock().await;
671
+
672
+ for attempt in 0..MAX_TRIES {
673
+ let request_id = protocol::util::generate_request_id();
674
+
675
+ // Check if this ID is already in use
676
+ if !requests.contains(&request_id) {
677
+ // Insert the ID and return it
678
+ requests.insert(request_id);
679
+ return Ok(request_id);
680
+ }
681
+
682
+ // Collision occurred (extremely rare with 4 bytes = 4 billion possibilities)
683
+ // Generate a new ID and try again
684
+ tracing::warn!(
685
+ ?request_id,
686
+ attempt,
687
+ "request id collision, generating new id"
688
+ );
689
+ }
690
+
691
+ bail!(
692
+ "failed to generate unique request id after {} attempts",
693
+ MAX_TRIES
694
+ );
695
+ }
696
+ }
697
+
698
+ // Helper function to choose a random target from a list of targets
699
+ fn choose_random_target(targets: &[RouteTarget]) -> Option<&RouteTarget> {
700
+ if targets.is_empty() {
701
+ return None;
702
+ }
703
+
704
+ // Use a simple random index selection
705
+ let random_index = rand::random::<usize>() % targets.len();
706
+ targets.get(random_index)
707
+ }
708
+
709
+ // Proxy service
710
+ pub struct ProxyService {
711
+ state: Arc<ProxyState>,
712
+ remote_addr: SocketAddr,
713
+ // Note: Using the hyper legacy client is the only option currently.
714
+ // This is what reqwest uses under the hood. Eventually we'll migrate to h3 once it's ready.
715
+ client: Client<hyper_util::client::legacy::connect::HttpConnector, Full<Bytes>>,
716
+ }
717
+
718
+ impl ProxyService {
719
+ pub fn new(state: Arc<ProxyState>, remote_addr: SocketAddr) -> Self {
720
+ // Create a client with the hyper-util legacy client
721
+ let client = Client::builder(TokioExecutor::new())
722
+ .pool_idle_timeout(Duration::from_secs(30))
723
+ .build_http();
724
+
725
+ Self {
726
+ state,
727
+ remote_addr,
728
+ client,
729
+ }
730
+ }
731
+
732
+ // Calculate backoff duration for a given retry attempt
733
+ pub fn calculate_backoff(attempt: u32, initial_interval: u64) -> Duration {
734
+ Duration::from_millis(initial_interval * 2u64.pow(attempt - 1))
735
+ }
736
+
737
+ #[tracing::instrument(skip_all)]
738
+ async fn handle_request(
739
+ &self,
740
+ req: Request<BodyIncoming>,
741
+ start_time: Instant,
742
+ request_context: &mut RequestContext,
743
+ ) -> Result<Response<ResponseBody>> {
744
+ let host = req
745
+ .headers()
746
+ .get(hyper::header::HOST)
747
+ .and_then(|h| h.to_str().ok())
748
+ .unwrap_or("unknown");
749
+
750
+ let path = req
751
+ .uri()
752
+ .path_and_query()
753
+ .map(|x| x.to_string())
754
+ .unwrap_or_else(|| req.uri().path().to_string());
755
+
756
+ // Set request body size in analytics (will be updated with actual size later)
757
+
758
+ let target_res = self
759
+ .state
760
+ .resolve_route(
761
+ host,
762
+ &path,
763
+ req.method(),
764
+ self.state.port_type.clone(),
765
+ req.headers(),
766
+ false,
767
+ )
768
+ .await;
769
+
770
+ let duration_secs = start_time.elapsed().as_secs_f64();
771
+ metrics::RESOLVE_ROUTE_DURATION.record(duration_secs, &[]);
772
+
773
+ // Resolve target
774
+ let target = target_res?;
775
+ if let ResolveRouteOutput::Response(response) = &target {
776
+ // Return the custom response
777
+ return response.build_response();
778
+ }
779
+
780
+ let actor_id = if let ResolveRouteOutput::Target(target) = &target {
781
+ target.actor_id
782
+ } else {
783
+ None
784
+ };
785
+
786
+ // Extract IP address from X-Forwarded-For header or fall back to remote_addr
787
+ let client_ip = req
788
+ .headers()
789
+ .get(X_FORWARDED_FOR)
790
+ .and_then(|h| h.to_str().ok())
791
+ .and_then(|forwarded| {
792
+ // X-Forwarded-For can be a comma-separated list, take the first IP
793
+ forwarded.split(',').next().map(|s| s.trim())
794
+ })
795
+ .and_then(|ip_str| ip_str.parse::<std::net::IpAddr>().ok())
796
+ .unwrap_or_else(|| self.remote_addr.ip());
797
+
798
+ // Apply rate limiting
799
+ if !self
800
+ .state
801
+ .check_rate_limit(client_ip, &actor_id, req.headers())
802
+ .await?
803
+ {
804
+ return Err(errors::RateLimit {
805
+ actor_id,
806
+ method: req.method().to_string(),
807
+ path: path.clone(),
808
+ ip: client_ip.to_string(),
809
+ }
810
+ .build());
811
+ }
812
+
813
+ // Acquire in-flight limit and generate request ID
814
+ let request_id = match self
815
+ .state
816
+ .acquire_in_flight(client_ip, &actor_id, req.headers())
817
+ .await?
818
+ {
819
+ Some(id) => id,
820
+ None => {
821
+ return Err(errors::RateLimit {
822
+ actor_id,
823
+ method: req.method().to_string(),
824
+ path: path.clone(),
825
+ ip: client_ip.to_string(),
826
+ }
827
+ .build());
828
+ }
829
+ };
830
+
831
+ // Increment metrics
832
+ metrics::PROXY_REQUEST_PENDING.add(1, &[]);
833
+ metrics::PROXY_REQUEST_TOTAL.add(1, &[]);
834
+
835
+ // Update request context with target info
836
+ if let Some(actor_id) = actor_id {
837
+ request_context.service_actor_id = Some(actor_id);
838
+ }
839
+
840
+ let res = if hyper_tungstenite::is_upgrade_request(&req) {
841
+ self.handle_websocket_upgrade(req, target, request_context, client_ip, actor_id)
842
+ .await
843
+ } else {
844
+ self.handle_http_request(req, target, request_context, client_ip, actor_id)
845
+ .await
846
+ };
847
+
848
+ let status = match &res {
849
+ Ok(resp) => resp.status().as_u16().to_string(),
850
+ Err(_) => "error".to_string(),
851
+ };
852
+
853
+ // Record metrics
854
+ let duration_secs = start_time.elapsed().as_secs_f64();
855
+ metrics::PROXY_REQUEST_DURATION
856
+ .record(duration_secs, &[KeyValue::new("status", status.clone())]);
857
+
858
+ metrics::PROXY_REQUEST_PENDING.add(-1, &[]);
859
+
860
+ // Release in-flight counter and request ID when done
861
+ let state_clone = self.state.clone();
862
+ tokio::spawn(
863
+ async move {
864
+ state_clone
865
+ .release_in_flight(client_ip, &actor_id, request_id)
866
+ .await;
867
+ }
868
+ .instrument(tracing::info_span!("release_in_flight_task")),
869
+ );
870
+
871
+ res
872
+ }
873
+
874
+ #[tracing::instrument(skip_all)]
875
+ async fn handle_http_request(
876
+ &self,
877
+ req: Request<BodyIncoming>,
878
+ resolved_route: ResolveRouteOutput,
879
+ request_context: &mut RequestContext,
880
+ client_ip: std::net::IpAddr,
881
+ actor_id: Option<Id>,
882
+ ) -> Result<Response<ResponseBody>> {
883
+ // Get middleware config for this actor if it exists
884
+ let middleware_config = if let ResolveRouteOutput::Target(target) = &resolved_route
885
+ && let Some(actor_id) = &target.actor_id
886
+ {
887
+ self.state
888
+ .get_middleware_config(actor_id, req.headers())
889
+ .await?
890
+ } else {
891
+ // Default middleware config for targets without actor_id
892
+ MiddlewareConfig {
893
+ rate_limit: RateLimitConfig {
894
+ requests: 100, // 100 requests
895
+ period: 60, // per 60 seconds
896
+ },
897
+ max_in_flight: MaxInFlightConfig {
898
+ amount: 20, // 20 concurrent requests
899
+ },
900
+ retry: RetryConfig {
901
+ max_attempts: 3, // 3 retry attempts
902
+ initial_interval: 100, // 100ms initial interval
903
+ },
904
+ timeout: TimeoutConfig {
905
+ request_timeout: 30, // 30 seconds for requests
906
+ },
907
+ }
908
+ };
909
+
910
+ let host = req
911
+ .headers()
912
+ .get(hyper::header::HOST)
913
+ .and_then(|h| h.to_str().ok())
914
+ .unwrap_or("unknown")
915
+ .to_string();
916
+
917
+ let path = req
918
+ .uri()
919
+ .path_and_query()
920
+ .map(|x| x.to_string())
921
+ .unwrap_or_else(|| req.uri().path().to_string());
922
+
923
+ // Set up retry with backoff from middleware config
924
+ let max_attempts = middleware_config.retry.max_attempts;
925
+ let initial_interval = middleware_config.retry.initial_interval;
926
+ let timeout_duration = Duration::from_secs(middleware_config.timeout.request_timeout);
927
+
928
+ match resolved_route {
929
+ ResolveRouteOutput::Target(mut target) => {
930
+ // Set service IP from target
931
+ if let Ok(target_ip) =
932
+ format!("{}:{}", target.host, target.port).parse::<std::net::SocketAddr>()
933
+ {
934
+ request_context.service_ip = Some(target_ip.ip());
935
+ }
936
+
937
+ // Read the request body before proceeding with retries
938
+ let (req_parts, body) = req.into_parts();
939
+ let req_body = match http_body_util::BodyExt::collect(body).await {
940
+ Ok(collected) => collected.to_bytes(),
941
+ Err(err) => {
942
+ tracing::debug!(?err, "Failed to read request body");
943
+ Bytes::new()
944
+ }
945
+ };
946
+
947
+ // Set actual request body size in analytics
948
+ request_context.client_request_body_bytes = Some(req_body.len() as u64);
949
+
950
+ // Use a value-returning loop to handle both errors and successful responses
951
+ let mut attempts = 0;
952
+ while attempts < max_attempts {
953
+ attempts += 1;
954
+
955
+ // Use the common function to build request parts
956
+ let builder = self
957
+ .proxied_request_builder(&req_parts, &target)
958
+ .map_err(|err| errors::HttpRequestBuildFailed(err.to_string()).build())?;
959
+
960
+ // Create the final request with body
961
+ let proxied_req = builder
962
+ .body(Full::<Bytes>::new(req_body.clone()))
963
+ .map_err(|err| errors::RequestBuildError(err.to_string()).build())?;
964
+
965
+ // Send the request with timeout
966
+ let res = timeout(timeout_duration, self.client.request(proxied_req))
967
+ .await
968
+ .map_err(|_| {
969
+ errors::RequestTimeout {
970
+ timeout_seconds: timeout_duration.as_secs(),
971
+ }
972
+ .build()
973
+ })?;
974
+
975
+ match res {
976
+ Ok(resp) => {
977
+ // Check if this is a retryable response
978
+ if should_retry_request_inner(resp.status(), resp.headers()) {
979
+ // Request connect error, might retry
980
+ tracing::debug!(
981
+ "Request attempt {attempts} failed (service unavailable)"
982
+ );
983
+
984
+ // Use backoff and continue
985
+ let backoff = Self::calculate_backoff(attempts, initial_interval);
986
+ tokio::time::sleep(backoff).await;
987
+
988
+ // Resolve target again, this time ignoring cache. This makes sure
989
+ // we always re-fetch the route on error
990
+ let ResolveRouteOutput::Target(new_target) = self
991
+ .state
992
+ .resolve_route(
993
+ &host,
994
+ &path,
995
+ &req_parts.method,
996
+ self.state.port_type.clone(),
997
+ &req_parts.headers,
998
+ true,
999
+ )
1000
+ .await?
1001
+ else {
1002
+ bail!("resolved route does not match Target");
1003
+ };
1004
+ target = new_target;
1005
+
1006
+ continue;
1007
+ }
1008
+
1009
+ let (parts, body) = resp.into_parts();
1010
+
1011
+ // Check if this is a streaming response by examining headers
1012
+ // let is_streaming = parts.headers.get("content-type")
1013
+ // .and_then(|ct| ct.to_str().ok())
1014
+ // .map(|ct| ct.contains("text/event-stream") || ct.contains("application/stream"))
1015
+ // .unwrap_or(false);
1016
+ let is_streaming = true;
1017
+
1018
+ if is_streaming {
1019
+ // For streaming responses, pass through the body without buffering
1020
+ tracing::debug!("Detected streaming response, preserving stream");
1021
+
1022
+ // We can't easily calculate response size for streaming, so set it to None
1023
+ request_context.guard_response_body_bytes = None;
1024
+
1025
+ let streaming_body = ResponseBody::Incoming(body);
1026
+ return Ok(Response::from_parts(parts, streaming_body));
1027
+ } else {
1028
+ // For non-streaming responses, buffer as before
1029
+ let body_bytes = match BodyExt::collect(body).await {
1030
+ Ok(collected) => collected.to_bytes(),
1031
+ Err(_) => Bytes::new(),
1032
+ };
1033
+
1034
+ // Set actual response body size in analytics
1035
+ request_context.guard_response_body_bytes =
1036
+ Some(body_bytes.len() as u64);
1037
+
1038
+ let full_body = ResponseBody::Full(Full::new(body_bytes));
1039
+ return Ok(Response::from_parts(parts, full_body));
1040
+ }
1041
+ }
1042
+ Err(err) => {
1043
+ if !err.is_connect() || attempts >= max_attempts {
1044
+ tracing::error!(
1045
+ ?err,
1046
+ ?target,
1047
+ "Request error after {} attempts",
1048
+ attempts
1049
+ );
1050
+
1051
+ return Err(errors::UpstreamError(format!(
1052
+ "Failed to connect to runner: {err}. Make sure your runners are healthy."
1053
+ ))
1054
+ .build());
1055
+ } else {
1056
+ // Request connect error, might retry
1057
+ tracing::debug!(?err, "Request attempt {attempts} failed");
1058
+
1059
+ // Use backoff and continue
1060
+ let backoff = Self::calculate_backoff(attempts, initial_interval);
1061
+ tokio::time::sleep(backoff).await;
1062
+
1063
+ // Resolve target again, this time ignoring cache. This makes sure
1064
+ // we always re-fetch the route on error
1065
+ let ResolveRouteOutput::Target(new_target) = self
1066
+ .state
1067
+ .resolve_route(
1068
+ &host,
1069
+ &path,
1070
+ &req_parts.method,
1071
+ self.state.port_type.clone(),
1072
+ &req_parts.headers,
1073
+ true,
1074
+ )
1075
+ .await?
1076
+ else {
1077
+ bail!("resolved route does not match Target");
1078
+ };
1079
+ target = new_target;
1080
+
1081
+ continue;
1082
+ }
1083
+ }
1084
+ }
1085
+ }
1086
+
1087
+ // If we get here, all attempts failed
1088
+ return Err(errors::RetryAttemptsExceeded {
1089
+ attempts: max_attempts,
1090
+ }
1091
+ .build());
1092
+ }
1093
+ ResolveRouteOutput::Response(_) => {
1094
+ unreachable!()
1095
+ }
1096
+ ResolveRouteOutput::CustomServe(mut handler) => {
1097
+ let req_headers = req.headers().clone();
1098
+ let req_method = req.method().clone();
1099
+
1100
+ // Acquire in-flight limit and generate request ID
1101
+ let request_id = match self
1102
+ .state
1103
+ .acquire_in_flight(client_ip, &actor_id, &req_headers)
1104
+ .await?
1105
+ {
1106
+ Some(id) => id,
1107
+ None => {
1108
+ return Err(errors::RateLimit {
1109
+ actor_id,
1110
+ method: req_method.to_string(),
1111
+ path: path.clone(),
1112
+ ip: client_ip.to_string(),
1113
+ }
1114
+ .build());
1115
+ }
1116
+ };
1117
+
1118
+ // Collect request body
1119
+ let (req_parts, body) = req.into_parts();
1120
+ let collected_body = match http_body_util::BodyExt::collect(body).await {
1121
+ Ok(collected) => collected.to_bytes(),
1122
+ Err(err) => {
1123
+ tracing::debug!(?err, "Failed to read request body");
1124
+ Bytes::new()
1125
+ }
1126
+ };
1127
+ let req_collected = hyper::Request::from_parts(
1128
+ req_parts,
1129
+ Full::<Bytes>::new(collected_body.clone()),
1130
+ );
1131
+
1132
+ // Attempt request
1133
+ let mut attempts = 0;
1134
+ while attempts < max_attempts {
1135
+ attempts += 1;
1136
+
1137
+ let res = handler
1138
+ .handle_request(req_collected.clone(), request_context, request_id)
1139
+ .await;
1140
+ if should_retry_request(&res) {
1141
+ // Request connect error, might retry
1142
+ tracing::debug!("Request attempt {attempts} failed (service unavailable)");
1143
+
1144
+ // Use backoff and continue
1145
+ let backoff = Self::calculate_backoff(attempts, initial_interval);
1146
+ tokio::time::sleep(backoff).await;
1147
+
1148
+ // Refresh route (ignore cache) so subsequent requests can hit new target
1149
+ let ResolveRouteOutput::CustomServe(new_handler) = self
1150
+ .state
1151
+ .resolve_route(
1152
+ &host,
1153
+ &path,
1154
+ req_collected.method(),
1155
+ self.state.port_type.clone(),
1156
+ &req_headers,
1157
+ true,
1158
+ )
1159
+ .await?
1160
+ else {
1161
+ bail!("resolved route does not match CustomServe");
1162
+ };
1163
+ handler = new_handler;
1164
+
1165
+ continue;
1166
+ }
1167
+
1168
+ // Release in-flight counter and request ID before returning
1169
+ self.state
1170
+ .release_in_flight(client_ip, &actor_id, request_id)
1171
+ .await;
1172
+ return res;
1173
+ }
1174
+
1175
+ // If we get here, all attempts failed
1176
+ // Release in-flight counter and request ID before returning error
1177
+ self.state
1178
+ .release_in_flight(client_ip, &actor_id, request_id)
1179
+ .await;
1180
+ return Err(errors::RetryAttemptsExceeded {
1181
+ attempts: max_attempts,
1182
+ }
1183
+ .build());
1184
+ }
1185
+ }
1186
+ }
1187
+
1188
+ /// Modifies the incoming request before it is proxied.
1189
+ fn proxied_request_builder(
1190
+ &self,
1191
+ req_parts: &hyper::http::request::Parts,
1192
+ target: &RouteTarget,
1193
+ ) -> Result<hyper::http::request::Builder> {
1194
+ let scheme = if target.port == 443 { "https" } else { "http" };
1195
+
1196
+ // Bracket raw IPv6 hosts
1197
+ let host = if target.host.contains(':') && !target.host.starts_with('[') {
1198
+ format!("[{}]", target.host)
1199
+ } else {
1200
+ target.host.clone()
1201
+ };
1202
+
1203
+ // Ensure path starts with a leading slash
1204
+ let path = if target.path.starts_with('/') {
1205
+ target.path.clone()
1206
+ } else {
1207
+ format!("/{}", target.path)
1208
+ };
1209
+
1210
+ let url = Url::parse(&format!("{scheme}://{host}:{}{}", target.port, path))
1211
+ .context("invalid scheme/host/port when building URL")?;
1212
+
1213
+ // Build the proxied request
1214
+ let mut builder = hyper::Request::builder()
1215
+ .method(req_parts.method.clone())
1216
+ .uri(url.to_string());
1217
+
1218
+ // Modify proxy headers
1219
+ let headers = builder
1220
+ .headers_mut()
1221
+ .expect("request builder unexpectedly in error state");
1222
+
1223
+ headers.remove(X_RIVET_TARGET);
1224
+ headers.remove(X_RIVET_ACTOR);
1225
+ headers.remove(X_RIVET_TOKEN);
1226
+
1227
+ add_proxy_headers_with_addr(headers, &req_parts.headers, self.remote_addr)?;
1228
+
1229
+ Ok(builder)
1230
+ }
1231
+
1232
+ #[tracing::instrument(skip_all)]
1233
+ async fn handle_websocket_upgrade(
1234
+ &self,
1235
+ req: Request<BodyIncoming>,
1236
+ target: ResolveRouteOutput,
1237
+ request_context: &mut RequestContext,
1238
+ client_ip: std::net::IpAddr,
1239
+ actor_id: Option<Id>,
1240
+ ) -> Result<Response<ResponseBody>> {
1241
+ // Parsed for retries later
1242
+ let req_host = req
1243
+ .headers()
1244
+ .get(hyper::header::HOST)
1245
+ .and_then(|h| h.to_str().ok())
1246
+ .unwrap_or("unknown")
1247
+ .to_string();
1248
+ let req_path = req
1249
+ .uri()
1250
+ .path_and_query()
1251
+ .map(|x| x.to_string())
1252
+ .unwrap_or_else(|| req.uri().path().to_string());
1253
+
1254
+ // Capture headers and method before request is consumed
1255
+ let req_headers = req.headers().clone();
1256
+ let req_method = req.method().clone();
1257
+ let ray_id = req.extensions().get::<RequestIds>().map(|x| x.ray_id);
1258
+
1259
+ // Get middleware config for this actor if it exists
1260
+ let middleware_config = match &actor_id {
1261
+ Some(actor_id) => {
1262
+ self.state
1263
+ .get_middleware_config(actor_id, &req_headers)
1264
+ .await?
1265
+ }
1266
+ None => {
1267
+ // Default middleware config for targets without actor_id
1268
+ tracing::debug!("Using default middleware config (no actor_id)");
1269
+ MiddlewareConfig {
1270
+ rate_limit: RateLimitConfig {
1271
+ requests: 100, // 100 requests
1272
+ period: 60, // per 60 seconds
1273
+ },
1274
+ max_in_flight: MaxInFlightConfig {
1275
+ amount: 20, // 20 concurrent requests
1276
+ },
1277
+ retry: RetryConfig {
1278
+ max_attempts: 3, // 3 retry attempts
1279
+ initial_interval: 100, // 100ms initial interval
1280
+ },
1281
+ timeout: TimeoutConfig {
1282
+ request_timeout: 30, // 30 seconds for requests
1283
+ },
1284
+ }
1285
+ }
1286
+ };
1287
+
1288
+ // Set up retry with backoff from middleware config
1289
+ let max_attempts = middleware_config.retry.max_attempts;
1290
+ let initial_interval = middleware_config.retry.initial_interval;
1291
+
1292
+ // Log the headers for debugging
1293
+ tracing::debug!("WebSocket upgrade request headers:");
1294
+ for (name, value) in req.headers() {
1295
+ if let Ok(val) = value.to_str() {
1296
+ tracing::debug!(" {}: {}", name, val);
1297
+ }
1298
+ }
1299
+
1300
+ // Handle WebSocket upgrade properly with hyper_tungstenite
1301
+ tracing::debug!(%req_path, "Upgrading client connection to WebSocket");
1302
+ let (client_response, client_ws) = match hyper_tungstenite::upgrade(req, None) {
1303
+ Ok(x) => {
1304
+ tracing::debug!("Client WebSocket upgrade successful");
1305
+ x
1306
+ }
1307
+ Err(err) => {
1308
+ tracing::error!(?err, "Failed to upgrade client WebSocket");
1309
+ return Err(errors::ConnectionError {
1310
+ error_message: format!("Failed to upgrade client WebSocket: {}", err),
1311
+ remote_addr: self.remote_addr.to_string(),
1312
+ }
1313
+ .build());
1314
+ }
1315
+ };
1316
+
1317
+ // Log response status and headers
1318
+ tracing::debug!(
1319
+ "Client upgrade response status: {}",
1320
+ client_response.status()
1321
+ );
1322
+ for (name, value) in client_response.headers() {
1323
+ if let Ok(val) = value.to_str() {
1324
+ tracing::debug!("Client upgrade response header - {}: {}", name, val);
1325
+ }
1326
+ }
1327
+
1328
+ // Clone needed values for the spawned task
1329
+ let state = self.state.clone();
1330
+ let remote_addr = self.remote_addr;
1331
+
1332
+ // Spawn a new task to handle the WebSocket bidirectional communication
1333
+ match target {
1334
+ ResolveRouteOutput::Target(mut target) => {
1335
+ tracing::debug!("Spawning task to handle WebSocket communication");
1336
+ self.state.tasks.spawn(
1337
+ async move {
1338
+ // Set up a timeout for the entire operation
1339
+ let timeout_duration = Duration::from_secs(30); // 30 seconds timeout
1340
+ tracing::debug!(
1341
+ "WebSocket proxy task started with {}s timeout",
1342
+ timeout_duration.as_secs()
1343
+ );
1344
+
1345
+ // Use retry logic to connect to the upstream WebSocket server
1346
+ let mut attempts = 0;
1347
+ let mut upstream_ws = None;
1348
+
1349
+ // First, wait for the client WebSocket to be ready (do this first to avoid race conditions)
1350
+ tracing::debug!("Waiting for client WebSocket to be ready...");
1351
+ let mut client_ws =
1352
+ match tokio::time::timeout(timeout_duration, client_ws).await {
1353
+ Ok(Ok(ws)) => {
1354
+ tracing::debug!("Client WebSocket is ready");
1355
+ ws
1356
+ }
1357
+ Ok(Err(err)) => {
1358
+ tracing::error!(?err, "Failed to get client WebSocket");
1359
+ return;
1360
+ }
1361
+ Err(_) => {
1362
+ tracing::error!(
1363
+ "Timeout waiting for client WebSocket to be ready after {}s",
1364
+ timeout_duration.as_secs()
1365
+ );
1366
+ return;
1367
+ }
1368
+ };
1369
+
1370
+ // Now attempt to connect to the upstream server
1371
+ tracing::debug!("Attempting connect to upstream WebSocket");
1372
+ while attempts < max_attempts {
1373
+ attempts += 1;
1374
+
1375
+ // Build the WebSocket URL using the url crate to properly handle IPv6 addresses
1376
+ let mut ws_url = match Url::parse("ws://example.com") {
1377
+ Ok(url) => url,
1378
+ Err(err) => {
1379
+ tracing::error!(?err, "Failed to create base WebSocket URL");
1380
+ return;
1381
+ }
1382
+ };
1383
+
1384
+ // Wrap IPv6 addresses in brackets if not already wrapped
1385
+ let host = if target.host.contains(':') && !target.host.starts_with('[')
1386
+ {
1387
+ format!("[{}]", target.host)
1388
+ } else {
1389
+ target.host.clone()
1390
+ };
1391
+
1392
+ if let Err(err) = ws_url.set_host(Some(&host)) {
1393
+ tracing::error!(?err, ?host, "Failed to set WebSocket host");
1394
+ return;
1395
+ }
1396
+ if let Err(err) = ws_url.set_port(Some(target.port)) {
1397
+ tracing::error!(?err, "Failed to set WebSocket port");
1398
+ return;
1399
+ }
1400
+
1401
+ // Split path and query string
1402
+ if let Some(query_pos) = target.path.find('?') {
1403
+ let (path, query) = target.path.split_at(query_pos);
1404
+ ws_url.set_path(path);
1405
+ // Remove the leading '?' from query
1406
+ ws_url.set_query(Some(&query[1..]));
1407
+ } else {
1408
+ ws_url.set_path(&target.path);
1409
+ ws_url.set_query(None);
1410
+ }
1411
+
1412
+ let target_url = ws_url.to_string();
1413
+
1414
+ tracing::debug!(
1415
+ "WebSocket request attempt {}/{} to {}",
1416
+ attempts,
1417
+ max_attempts,
1418
+ target_url
1419
+ );
1420
+
1421
+ // Build the websocket request with headers
1422
+ let mut ws_request = match target_url.into_client_request() {
1423
+ Ok(req) => req,
1424
+ Err(err) => {
1425
+ tracing::error!(?err, "Failed to create websocket request");
1426
+ return;
1427
+ }
1428
+ };
1429
+
1430
+ // Add proxy headers to the websocket request
1431
+ if let Err(err) = add_proxy_headers_with_addr(
1432
+ ws_request.headers_mut(),
1433
+ &req_headers,
1434
+ remote_addr,
1435
+ ) {
1436
+ tracing::error!(
1437
+ ?err,
1438
+ "Failed to add proxy headers to websocket request"
1439
+ );
1440
+ return;
1441
+ }
1442
+
1443
+ match tokio::time::timeout(
1444
+ Duration::from_secs(5), // 5 second timeout per connection attempt
1445
+ tokio_tungstenite::connect_async(ws_request),
1446
+ )
1447
+ .await
1448
+ {
1449
+ Ok(Ok((ws_stream, resp))) => {
1450
+ tracing::debug!(
1451
+ "Successfully connected to upstream WebSocket server"
1452
+ );
1453
+ tracing::debug!(
1454
+ "Upstream connection response status: {:?}",
1455
+ resp.status()
1456
+ );
1457
+
1458
+ // Log headers for debugging
1459
+ for (name, value) in resp.headers() {
1460
+ if let Ok(val) = value.to_str() {
1461
+ tracing::debug!(
1462
+ "Upstream response header - {}: {}",
1463
+ name,
1464
+ val
1465
+ );
1466
+ }
1467
+ }
1468
+
1469
+ upstream_ws = Some(ws_stream);
1470
+ break;
1471
+ }
1472
+ Ok(Err(err)) => {
1473
+ tracing::debug!(
1474
+ ?err,
1475
+ "WebSocket request attempt {} failed",
1476
+ attempts
1477
+ );
1478
+ }
1479
+ Err(_) => {
1480
+ tracing::debug!(
1481
+ "WebSocket request attempt {} timed out after 5s",
1482
+ attempts
1483
+ );
1484
+ }
1485
+ }
1486
+
1487
+ // Check if we've reached max attempts
1488
+ if attempts >= max_attempts {
1489
+ tracing::debug!(
1490
+ "All {} WebSocket connection attempts failed",
1491
+ max_attempts
1492
+ );
1493
+
1494
+ // Send a close message to the client since we can't connect to upstream
1495
+ tracing::debug!(
1496
+ "Sending close message to client due to upstream connection failure"
1497
+ );
1498
+ let (mut client_sink, _) = client_ws.split();
1499
+ match client_sink
1500
+ .send(to_hyper_close(Some(err_to_close_frame(
1501
+ errors::RetryAttemptsExceeded { attempts }.build(),
1502
+ ray_id,
1503
+ ))))
1504
+ .await
1505
+ {
1506
+ Ok(_) => {
1507
+ tracing::trace!("Successfully sent close message to client")
1508
+ }
1509
+ Err(err) => {
1510
+ tracing::error!(
1511
+ ?err,
1512
+ "Failed to send close message to client"
1513
+ )
1514
+ }
1515
+ };
1516
+
1517
+ match client_sink.flush().await {
1518
+ Ok(_) => {
1519
+ tracing::trace!(
1520
+ "Successfully flushed client sink after close"
1521
+ )
1522
+ }
1523
+ Err(err) => {
1524
+ tracing::error!(
1525
+ ?err,
1526
+ "Failed to flush client sink after close"
1527
+ )
1528
+ }
1529
+ };
1530
+
1531
+ return;
1532
+ }
1533
+
1534
+ // Use backoff for the next attempt
1535
+ let backoff = Self::calculate_backoff(attempts, initial_interval);
1536
+ tracing::debug!(
1537
+ "Waiting for {:?} before next connection attempt",
1538
+ backoff
1539
+ );
1540
+
1541
+ tokio::time::sleep(backoff).await;
1542
+
1543
+ // Resolve target again, this time ignoring cache. This makes sure
1544
+ // we always re-fetch the route on error
1545
+ let new_target = state
1546
+ .resolve_route(
1547
+ &req_host,
1548
+ &req_path,
1549
+ &req_method,
1550
+ state.port_type.clone(),
1551
+ &req_headers,
1552
+ true,
1553
+ )
1554
+ .await;
1555
+
1556
+ match new_target {
1557
+ Ok(ResolveRouteOutput::Target(new_target)) => {
1558
+ target = new_target;
1559
+ }
1560
+ Ok(ResolveRouteOutput::Response(response)) => {
1561
+ tracing::debug!(
1562
+ status=?response.status,
1563
+ message=?response.message,
1564
+ docs=?response.docs,
1565
+ "got response instead of websocket target",
1566
+ );
1567
+
1568
+ // Close the WebSocket connection with the response message
1569
+ let _ = client_ws
1570
+ .close(Some(str_to_close_frame(response.message.as_ref())))
1571
+ .await;
1572
+ return;
1573
+ }
1574
+ Ok(ResolveRouteOutput::CustomServe(_)) => {
1575
+ let _ = client_ws
1576
+ .close(Some(err_to_close_frame(
1577
+ errors::WebSocketTargetChanged.build(),
1578
+ ray_id,
1579
+ )))
1580
+ .await;
1581
+ return;
1582
+ }
1583
+ Err(err) => {
1584
+ tracing::error!(?err, "Routing error");
1585
+ }
1586
+ }
1587
+ }
1588
+
1589
+ // If we couldn't connect to the upstream server, exit the task
1590
+ let upstream_ws = match upstream_ws {
1591
+ Some(ws) => {
1592
+ tracing::debug!(
1593
+ "Successfully established upstream WebSocket connection"
1594
+ );
1595
+ ws
1596
+ }
1597
+ Option::None => {
1598
+ tracing::error!(
1599
+ "Failed to establish upstream WebSocket connection (unexpected)"
1600
+ );
1601
+ return; // Should never happen due to checks above, but just in case
1602
+ }
1603
+ };
1604
+
1605
+ // Now set up bidirectional communication between the client and upstream WebSockets
1606
+ tracing::debug!("Setting up bidirectional WebSocket proxying");
1607
+ let (client_sink, client_stream) = client_ws.split();
1608
+ let (upstream_sink, upstream_stream) = upstream_ws.split();
1609
+
1610
+ // Create channels for coordinating shutdown between client and upstream
1611
+ let (shutdown_tx, shutdown_rx) = tokio::sync::watch::channel(false);
1612
+
1613
+ // Manually forward messages from client to upstream server with shutdown coordination
1614
+ let client_to_upstream = async {
1615
+ tracing::debug!("Starting client-to-upstream forwarder");
1616
+ let mut stream = client_stream;
1617
+ let mut sink = upstream_sink;
1618
+ let mut shutdown_rx = shutdown_rx.clone();
1619
+
1620
+ loop {
1621
+ tokio::select! {
1622
+ // Check for shutdown signal
1623
+ shutdown_result = shutdown_rx.changed() => {
1624
+ match shutdown_result {
1625
+ Ok(_) => {
1626
+ if *shutdown_rx.borrow() {
1627
+ tracing::debug!("Client-to-upstream forwarder shutting down due to signal");
1628
+ break;
1629
+ }
1630
+ },
1631
+ Err(err) => {
1632
+ // Channel closed
1633
+ tracing::debug!(?err, "Client-to-upstream shutdown channel closed");
1634
+ break;
1635
+ }
1636
+ }
1637
+ }
1638
+
1639
+ // Process next message from client
1640
+ msg_result = stream.next() => {
1641
+ match msg_result {
1642
+ Some(Ok(client_msg)) => {
1643
+ // Convert from hyper_tungstenite::Message to tokio_tungstenite::Message
1644
+ let upstream_msg = match client_msg {
1645
+ hyper_tungstenite::tungstenite::Message::Text(text) => {
1646
+ tokio_tungstenite::tungstenite::Message::Text(text)
1647
+ },
1648
+ hyper_tungstenite::tungstenite::Message::Binary(data) => {
1649
+ tokio_tungstenite::tungstenite::Message::Binary(data)
1650
+ },
1651
+ hyper_tungstenite::tungstenite::Message::Ping(data) => {
1652
+ tokio_tungstenite::tungstenite::Message::Ping(data)
1653
+ },
1654
+ hyper_tungstenite::tungstenite::Message::Pong(data) => {
1655
+ tokio_tungstenite::tungstenite::Message::Pong(data)
1656
+ },
1657
+ hyper_tungstenite::tungstenite::Message::Close(frame) => {
1658
+ // Signal shutdown to other direction
1659
+ let _ = shutdown_tx.send(true);
1660
+
1661
+ to_hyper_close(frame)
1662
+ },
1663
+ hyper_tungstenite::tungstenite::Message::Frame(_) => {
1664
+ // Skip frames - they're an implementation detail
1665
+ continue;
1666
+ },
1667
+ };
1668
+
1669
+ // Send the message with a timeout
1670
+ tracing::trace!("Sending message to upstream server");
1671
+ let send_result = tokio::time::timeout(
1672
+ Duration::from_secs(5),
1673
+ sink.send(upstream_msg)
1674
+ ).await;
1675
+
1676
+ match send_result {
1677
+ Ok(Ok(_)) => {
1678
+ tracing::trace!("Message sent to upstream successfully");
1679
+ // Flush the sink with a timeout
1680
+ tracing::trace!("Flushing upstream sink");
1681
+ let flush_result = tokio::time::timeout(
1682
+ Duration::from_secs(2),
1683
+ sink.flush()
1684
+ ).await;
1685
+
1686
+ if let Err(_) = flush_result {
1687
+ tracing::trace!("Timeout flushing upstream sink");
1688
+ let _ = shutdown_tx.send(true);
1689
+ break;
1690
+ } else if let Ok(Err(err)) = flush_result {
1691
+ tracing::trace!(?err, "Error flushing upstream sink");
1692
+ let _ = shutdown_tx.send(true);
1693
+ break;
1694
+ } else {
1695
+ tracing::trace!("Upstream sink flushed successfully");
1696
+ }
1697
+ },
1698
+ Ok(Err(err)) => {
1699
+ tracing::trace!(?err, "Error sending message to upstream");
1700
+ let _ = shutdown_tx.send(true);
1701
+ break;
1702
+ },
1703
+ Err(_) => {
1704
+ tracing::trace!("Timeout sending message to upstream after 5s");
1705
+ let _ = shutdown_tx.send(true);
1706
+ break;
1707
+ }
1708
+ }
1709
+ },
1710
+ Some(Err(err)) => {
1711
+ // Error receiving message from client
1712
+ tracing::trace!(?err, "Error receiving message from client");
1713
+ tracing::trace!(?err, "Error details");
1714
+ // Signal shutdown to other direction
1715
+ let _ = shutdown_tx.send(true);
1716
+ break;
1717
+ },
1718
+ None => {
1719
+ // End of stream
1720
+ tracing::trace!("Client WebSocket stream ended");
1721
+ // Signal shutdown to other direction
1722
+ let _ = shutdown_tx.send(true);
1723
+ break;
1724
+ }
1725
+ }
1726
+ }
1727
+ }
1728
+ }
1729
+
1730
+ // Try to send a close frame - ignore errors as the connection might already be closed
1731
+ tracing::trace!("Attempting to send close message to upstream");
1732
+ match sink
1733
+ .send(tokio_tungstenite::tungstenite::Message::Close(None))
1734
+ .await
1735
+ {
1736
+ Ok(_) => {
1737
+ tracing::trace!("Close message sent to upstream successfully")
1738
+ }
1739
+ Err(err) => {
1740
+ tracing::trace!(
1741
+ ?err,
1742
+ "Failed to send close message to upstream"
1743
+ )
1744
+ }
1745
+ };
1746
+
1747
+ match sink.flush().await {
1748
+ Ok(_) => {
1749
+ tracing::trace!(
1750
+ "Upstream sink flushed successfully after close"
1751
+ )
1752
+ }
1753
+ Err(err) => {
1754
+ tracing::trace!(
1755
+ ?err,
1756
+ "Failed to flush upstream sink after close"
1757
+ )
1758
+ }
1759
+ };
1760
+
1761
+ tracing::debug!("Client-to-upstream task completed");
1762
+ };
1763
+
1764
+ // Manually forward messages from upstream server to client with shutdown coordination
1765
+ let upstream_to_client = async {
1766
+ tracing::debug!("Starting upstream-to-client forwarder");
1767
+ let mut stream = upstream_stream;
1768
+ let mut sink = client_sink;
1769
+ let mut shutdown_rx = shutdown_rx.clone();
1770
+
1771
+ loop {
1772
+ tokio::select! {
1773
+ // Check for shutdown signal
1774
+ shutdown_result = shutdown_rx.changed() => {
1775
+ match shutdown_result {
1776
+ Ok(_) => {
1777
+ if *shutdown_rx.borrow() {
1778
+ tracing::debug!("Upstream-to-client forwarder shutting down due to signal");
1779
+ break;
1780
+ }
1781
+ },
1782
+ Err(err) => {
1783
+ // Channel closed
1784
+ tracing::debug!(?err, "Upstream-to-client shutdown channel closed");
1785
+ break;
1786
+ }
1787
+ }
1788
+ }
1789
+
1790
+ // Process next message from upstream
1791
+ msg_result = stream.next() => {
1792
+ match msg_result {
1793
+ Some(Ok(upstream_msg)) => {
1794
+ // Convert from tokio_tungstenite::Message to hyper_tungstenite::Message
1795
+ let client_msg = match upstream_msg {
1796
+ tokio_tungstenite::tungstenite::Message::Text(text) => {
1797
+ hyper_tungstenite::tungstenite::Message::Text(text)
1798
+ },
1799
+ tokio_tungstenite::tungstenite::Message::Binary(data) => {
1800
+ hyper_tungstenite::tungstenite::Message::Binary(data)
1801
+ },
1802
+ tokio_tungstenite::tungstenite::Message::Ping(data) => {
1803
+ hyper_tungstenite::tungstenite::Message::Ping(data)
1804
+ },
1805
+ tokio_tungstenite::tungstenite::Message::Pong(data) => {
1806
+ hyper_tungstenite::tungstenite::Message::Pong(data)
1807
+ },
1808
+ tokio_tungstenite::tungstenite::Message::Close(frame) => {
1809
+ // Signal shutdown to other direction
1810
+ let _ = shutdown_tx.send(true);
1811
+
1812
+ to_hyper_close(frame)
1813
+ },
1814
+ tokio_tungstenite::tungstenite::Message::Frame(_) => {
1815
+ // Skip frames - they're an implementation detail
1816
+ continue;
1817
+ },
1818
+ };
1819
+
1820
+ // Send the message with a timeout
1821
+ tracing::trace!("Sending message to client");
1822
+ let send_result = tokio::time::timeout(
1823
+ Duration::from_secs(5),
1824
+ sink.send(client_msg)
1825
+ ).await;
1826
+
1827
+ match send_result {
1828
+ Ok(Ok(_)) => {
1829
+ tracing::trace!("Message sent to client successfully");
1830
+ // Flush the sink with a timeout
1831
+ tracing::trace!("Flushing client sink");
1832
+ let flush_result = tokio::time::timeout(
1833
+ Duration::from_secs(2),
1834
+ sink.flush()
1835
+ ).await;
1836
+
1837
+ if let Err(_) = flush_result {
1838
+ tracing::trace!("Timeout flushing client sink");
1839
+ let _ = shutdown_tx.send(true);
1840
+ break;
1841
+ } else if let Ok(Err(err)) = flush_result {
1842
+ tracing::trace!(?err, "Error flushing client sink");
1843
+ let _ = shutdown_tx.send(true);
1844
+ break;
1845
+ } else {
1846
+ tracing::trace!("Client sink flushed successfully");
1847
+ }
1848
+ },
1849
+ Ok(Err(err)) => {
1850
+ tracing::trace!(?err, "Error sending message to client");
1851
+ let _ = shutdown_tx.send(true);
1852
+ break;
1853
+ },
1854
+ Err(_) => {
1855
+ tracing::trace!("Timeout sending message to client after 5s");
1856
+ let _ = shutdown_tx.send(true);
1857
+ break;
1858
+ }
1859
+ }
1860
+ },
1861
+ Some(Err(err)) => {
1862
+ // Error receiving message from upstream
1863
+ tracing::trace!(?err, "Error receiving message from upstream");
1864
+ // Signal shutdown to other direction
1865
+ let _ = shutdown_tx.send(true);
1866
+ break;
1867
+ },
1868
+ None => {
1869
+ // End of stream
1870
+ tracing::trace!("Upstream WebSocket stream ended");
1871
+ // Signal shutdown to other direction
1872
+ let _ = shutdown_tx.send(true);
1873
+ break;
1874
+ }
1875
+ }
1876
+ }
1877
+ }
1878
+ }
1879
+
1880
+ // Try to send a close frame - ignore errors as the connection might already be closed
1881
+ tracing::trace!("Attempting to send close message to client");
1882
+ match sink.send(to_hyper_close(None)).await {
1883
+ Ok(_) => {
1884
+ tracing::trace!("Close message sent to client successfully")
1885
+ }
1886
+ Err(err) => {
1887
+ tracing::trace!(?err, "Failed to send close message to client")
1888
+ }
1889
+ };
1890
+
1891
+ match sink.flush().await {
1892
+ Ok(_) => {
1893
+ tracing::trace!("Client sink flushed successfully after close")
1894
+ }
1895
+ Err(err) => {
1896
+ tracing::trace!(?err, "Failed to flush client sink after close")
1897
+ }
1898
+ };
1899
+
1900
+ tracing::trace!("Upstream-to-client task completed");
1901
+ };
1902
+
1903
+ // Run both directions concurrently until either one completes or errors
1904
+ tracing::debug!("Starting bidirectional message forwarding");
1905
+ tokio::join!(client_to_upstream, upstream_to_client);
1906
+ tracing::debug!("Bidirectional message forwarding completed");
1907
+ }
1908
+ .instrument(tracing::info_span!("handle_ws_task_target")),
1909
+ );
1910
+ }
1911
+ ResolveRouteOutput::Response(_) => unreachable!(),
1912
+ ResolveRouteOutput::CustomServe(mut handler) => {
1913
+ tracing::debug!(%req_path, "Spawning task to handle WebSocket communication");
1914
+ let mut request_context = request_context.clone();
1915
+ let req_headers = req_headers.clone();
1916
+ let state = self.state.clone();
1917
+ let req_path = req_path.clone();
1918
+ let req_host = req_host.clone();
1919
+ let req_method = req_method.clone();
1920
+
1921
+ self.state.tasks.spawn(
1922
+ async move {
1923
+ let request_id = match state
1924
+ .acquire_in_flight(client_ip, &actor_id, &req_headers)
1925
+ .await?
1926
+ {
1927
+ Some(id) => id,
1928
+ None => {
1929
+ return Err(errors::RateLimit {
1930
+ actor_id,
1931
+ method: req_method.to_string(),
1932
+ path: req_path.clone(),
1933
+ ip: client_ip.to_string(),
1934
+ }
1935
+ .build()
1936
+ .into());
1937
+ }
1938
+ };
1939
+ let mut ws_hibernation_close = false;
1940
+ let mut after_hibernation = false;
1941
+ let mut attempts = 0u32;
1942
+
1943
+ let ws_handle = WebSocketHandle::new(client_ws)
1944
+ .await
1945
+ .context("failed initiating websocket handle")?;
1946
+
1947
+ loop {
1948
+ match handler
1949
+ .handle_websocket(
1950
+ ws_handle.clone(),
1951
+ &req_headers,
1952
+ &req_path,
1953
+ &mut request_context,
1954
+ request_id,
1955
+ after_hibernation,
1956
+ )
1957
+ .await
1958
+ {
1959
+ Ok(close_frame) => {
1960
+ tracing::debug!("websocket handler complete, closing");
1961
+
1962
+ // Send graceful close. This may fail if client already sent
1963
+ // close frame, which is normal.
1964
+ tracing::debug!(?close_frame, "sending close frame to client");
1965
+ match ws_handle.send(to_hyper_close(close_frame)).await {
1966
+ Ok(_) => {
1967
+ tracing::debug!("close frame sent successfully");
1968
+ }
1969
+ Err(err) => {
1970
+ tracing::debug!(
1971
+ ?err,
1972
+ "failed to send close frame (websocket may be already closing)"
1973
+ );
1974
+ }
1975
+ }
1976
+
1977
+ // Flush to ensure close frame is sent
1978
+ tracing::debug!("flushing websocket");
1979
+ match ws_handle.flush().await {
1980
+ Ok(_) => {
1981
+ tracing::debug!("websocket flushed successfully");
1982
+ }
1983
+ Err(err) => {
1984
+ tracing::debug!(
1985
+ ?err,
1986
+ "failed to flush websocket (websocket may be already closing)"
1987
+ );
1988
+ }
1989
+ }
1990
+
1991
+ // Keep TCP connection open briefly to allow client to process close
1992
+ tokio::time::sleep(WEBSOCKET_CLOSE_LINGER).await;
1993
+
1994
+ break;
1995
+ }
1996
+ Err(err) => {
1997
+ tracing::debug!(?err, "websocket handler error");
1998
+
1999
+ // Denotes that the connection did not fail, but the downstream has closed
2000
+ let ws_hibernate = is_ws_hibernate(&err);
2001
+
2002
+ if ws_hibernate {
2003
+ attempts = 0;
2004
+ } else {
2005
+ attempts += 1;
2006
+ }
2007
+
2008
+ if ws_hibernate {
2009
+ // This should be unreachable because as soon as the actor is
2010
+ // reconnected to after hibernation the gateway will consume the close
2011
+ // frame from the client ws stream
2012
+ ensure!(
2013
+ !ws_hibernation_close,
2014
+ "should not be hibernating again after receiving a close frame during hibernation"
2015
+ );
2016
+
2017
+ // After this function returns:
2018
+ // - the route will be resolved again
2019
+ // - the websocket will connect to the new downstream target
2020
+ // - the gateway will continue reading messages from the client ws
2021
+ // (starting with the message that caused the hibernation to end)
2022
+ let res = handler
2023
+ .handle_websocket_hibernation(
2024
+ ws_handle.clone(),
2025
+ request_id,
2026
+ )
2027
+ .await?;
2028
+
2029
+ after_hibernation = true;
2030
+
2031
+ // Despite receiving a close frame from the client during hibernation
2032
+ // we are going to reconnect to the actor so that it knows the
2033
+ // connection has closed
2034
+ if let HibernationResult::Close = res {
2035
+ tracing::debug!("starting hibernating websocket close");
2036
+
2037
+ ws_hibernation_close = true;
2038
+ }
2039
+ } else if attempts > max_attempts
2040
+ || !is_retryable_ws_error(&err)
2041
+ {
2042
+ tracing::debug!(
2043
+ ?attempts,
2044
+ ?max_attempts,
2045
+ "WebSocket failed"
2046
+ );
2047
+
2048
+ // Close WebSocket with error
2049
+ ws_handle
2050
+ .send(to_hyper_close(Some(err_to_close_frame(
2051
+ err, ray_id,
2052
+ ))))
2053
+ .await?;
2054
+
2055
+ // Flush to ensure close frame is sent
2056
+ ws_handle.flush().await?;
2057
+
2058
+ // Keep TCP connection open briefly to allow client to process close
2059
+ tokio::time::sleep(WEBSOCKET_CLOSE_LINGER).await;
2060
+
2061
+ break;
2062
+ } else {
2063
+ let backoff = ProxyService::calculate_backoff(
2064
+ attempts,
2065
+ initial_interval,
2066
+ );
2067
+
2068
+ tracing::debug!(
2069
+ ?backoff,
2070
+ "WebSocket attempt {attempts} failed (service unavailable)"
2071
+ );
2072
+
2073
+ // Apply backoff for retryable error
2074
+ tokio::time::sleep(backoff).await;
2075
+ }
2076
+
2077
+ // Retry route resolution
2078
+ match state
2079
+ .resolve_route(
2080
+ &req_host,
2081
+ &req_path,
2082
+ &req_method,
2083
+ state.port_type.clone(),
2084
+ &req_headers,
2085
+ true,
2086
+ )
2087
+ .await
2088
+ {
2089
+ Ok(ResolveRouteOutput::CustomServe(new_handler)) => {
2090
+ handler = new_handler;
2091
+ continue;
2092
+ }
2093
+ Ok(ResolveRouteOutput::Response(response)) => {
2094
+ ws_handle
2095
+ .send(to_hyper_close(Some(str_to_close_frame(
2096
+ response.message.as_ref(),
2097
+ ))))
2098
+ .await?;
2099
+
2100
+ // Flush to ensure close frame is sent
2101
+ ws_handle.flush().await?;
2102
+
2103
+ // Keep TCP connection open briefly to allow client to process close
2104
+ tokio::time::sleep(WEBSOCKET_CLOSE_LINGER).await;
2105
+ }
2106
+ Ok(ResolveRouteOutput::Target(_)) => {
2107
+ ws_handle
2108
+ .send(to_hyper_close(Some(err_to_close_frame(
2109
+ errors::WebSocketTargetChanged.build(),
2110
+ ray_id,
2111
+ ))))
2112
+ .await?;
2113
+
2114
+ // Flush to ensure close frame is sent
2115
+ ws_handle.flush().await?;
2116
+
2117
+ // Keep TCP connection open briefly to allow client to process close
2118
+ tokio::time::sleep(WEBSOCKET_CLOSE_LINGER).await;
2119
+
2120
+ break;
2121
+ }
2122
+ Err(err) => {
2123
+ ws_handle
2124
+ .send(to_hyper_close(Some(err_to_close_frame(
2125
+ err, ray_id,
2126
+ ))))
2127
+ .await?;
2128
+
2129
+ // Flush to ensure close frame is sent
2130
+ ws_handle.flush().await?;
2131
+
2132
+ // Keep TCP connection open briefly to allow client to process close
2133
+ tokio::time::sleep(WEBSOCKET_CLOSE_LINGER).await;
2134
+
2135
+ break;
2136
+ }
2137
+ }
2138
+ }
2139
+ }
2140
+ }
2141
+
2142
+ // Release in-flight counter and request ID when task completes
2143
+ state
2144
+ .release_in_flight(client_ip, &actor_id, request_id)
2145
+ .await;
2146
+
2147
+ Ok(())
2148
+ }
2149
+ .instrument(tracing::info_span!("handle_ws_task_custom_serve")),
2150
+ );
2151
+ }
2152
+ }
2153
+
2154
+ // Return the response that will upgrade the client connection
2155
+ // For proper WebSocket handshaking, we need to preserve the original response
2156
+ // structure but convert it to our expected return type without modifying its content
2157
+ tracing::debug!("Returning WebSocket upgrade response to client");
2158
+ // Extract the parts from the response but preserve all headers and status
2159
+ let (mut parts, _) = client_response.into_parts();
2160
+
2161
+ // Add Sec-WebSocket-Protocol header to the response
2162
+ // Many WebSocket clients (e.g. node-ws & Cloudflare) require a protocol in the response
2163
+ parts.headers.insert(
2164
+ "sec-websocket-protocol",
2165
+ hyper::header::HeaderValue::from_static("rivet"),
2166
+ );
2167
+
2168
+ // Create a new response with an empty body - WebSocket upgrades don't need a body
2169
+ Ok(Response::from_parts(
2170
+ parts,
2171
+ ResponseBody::Full(Full::<Bytes>::new(Bytes::new())),
2172
+ ))
2173
+ }
2174
+ }
2175
+
2176
+ impl ProxyService {
2177
+ // Process an individual request
2178
+ #[tracing::instrument(name = "guard_request", skip_all, fields(ray_id, req_id))]
2179
+ pub async fn process(&self, mut req: Request<BodyIncoming>) -> Result<Response<ResponseBody>> {
2180
+ let start_time = Instant::now();
2181
+
2182
+ let request_ids = RequestIds::new(self.state.config.dc_label());
2183
+ req.extensions_mut().insert(request_ids);
2184
+
2185
+ tracing::Span::current()
2186
+ .record("req_id", request_ids.req_id.to_string())
2187
+ .record("ray_id", request_ids.ray_id.to_string());
2188
+
2189
+ // Create request context for analytics tracking
2190
+ let mut request_context =
2191
+ RequestContext::new(self.state.clickhouse_inserter.clone(), request_ids);
2192
+
2193
+ // Extract request information for logging and analytics before consuming the request
2194
+ let incoming_ray_id = req
2195
+ .headers()
2196
+ .get(X_RIVET_RAY_ID)
2197
+ .and_then(|h| h.to_str().ok())
2198
+ .and_then(|id| Id::parse(id).ok());
2199
+ let host = req
2200
+ .headers()
2201
+ .get(hyper::header::HOST)
2202
+ .and_then(|h| h.to_str().ok())
2203
+ .unwrap_or("unknown")
2204
+ .to_string();
2205
+ let uri_string = req.uri().to_string();
2206
+ let path = req
2207
+ .uri()
2208
+ .path_and_query()
2209
+ .map(|x| x.to_string())
2210
+ .unwrap_or_else(|| req.uri().path().to_string());
2211
+ let method = req.method().clone();
2212
+
2213
+ let user_agent = req
2214
+ .headers()
2215
+ .get(hyper::header::USER_AGENT)
2216
+ .and_then(|h| h.to_str().ok())
2217
+ .map(|s| s.to_string());
2218
+
2219
+ // Populate request context with available data
2220
+ request_context.client_ip = Some(self.remote_addr.ip());
2221
+ request_context.client_request_host = Some(host.clone());
2222
+ request_context.client_request_method = Some(method.to_string());
2223
+ request_context.client_request_path = Some(req.uri().path().to_string());
2224
+ request_context.client_request_protocol = Some(format!("{:?}", req.version()));
2225
+ request_context.client_request_scheme =
2226
+ Some(req.uri().scheme_str().unwrap_or("http").to_string());
2227
+ request_context.client_request_uri = Some(path.clone());
2228
+ request_context.client_src_port = Some(self.remote_addr.port());
2229
+
2230
+ if let Some(referer) = req
2231
+ .headers()
2232
+ .get(hyper::header::REFERER)
2233
+ .and_then(|h| h.to_str().ok())
2234
+ {
2235
+ request_context.client_request_referer = Some(referer.to_string());
2236
+ }
2237
+
2238
+ if let Some(ua) = &user_agent {
2239
+ request_context.client_request_user_agent = Some(ua.clone());
2240
+ }
2241
+
2242
+ if let Some(requested_with) = req
2243
+ .headers()
2244
+ .get("x-requested-with")
2245
+ .and_then(|h| h.to_str().ok())
2246
+ {
2247
+ request_context.client_x_requested_with = Some(requested_with.to_string());
2248
+ }
2249
+
2250
+ // TLS information would be set here if available (for HTTPS connections)
2251
+ // This requires TLS connection introspection and is marked for future enhancement
2252
+
2253
+ // Debug log request information with structured fields (Apache-like access log)
2254
+ tracing::debug!(
2255
+ ?incoming_ray_id,
2256
+ ray_id=?request_ids.ray_id,
2257
+ req_id=?request_ids.req_id,
2258
+ method = %method,
2259
+ path = %path,
2260
+ host = %host,
2261
+ remote_addr = %self.remote_addr,
2262
+ uri = %uri_string,
2263
+ protocol = ?self.state.port_type,
2264
+ user_agent = ?user_agent,
2265
+ "Request received"
2266
+ );
2267
+
2268
+ let is_websocket = hyper_tungstenite::is_upgrade_request(&req);
2269
+
2270
+ // Used for ws error proxying later
2271
+ let mut mock_req_builder = Request::builder()
2272
+ .method(req.method().clone())
2273
+ .uri(req.uri().clone())
2274
+ .version(req.version().clone());
2275
+ if let Some(headers) = mock_req_builder.headers_mut() {
2276
+ *headers = req.headers().clone();
2277
+ }
2278
+ if let Some(extensions) = mock_req_builder.extensions_mut() {
2279
+ *extensions = req.extensions().clone();
2280
+ }
2281
+ let mock_req = mock_req_builder.body(())?;
2282
+
2283
+ // Process the request
2284
+ let mut res = match self
2285
+ .handle_request(req, start_time, &mut request_context)
2286
+ .await
2287
+ {
2288
+ Ok(res) => res,
2289
+ Err(err) => {
2290
+ // Log the error
2291
+ tracing::error!(?err, "Request failed");
2292
+
2293
+ metrics::PROXY_REQUEST_ERROR
2294
+ .add(1, &[KeyValue::new("error_type", err.to_string())]);
2295
+
2296
+ // If we receive an error during a websocket request, we attempt to open the websocket anyway
2297
+ // so we can send the error via websocket instead of http. Most websocket clients don't handle
2298
+ // HTTP errors in a meaningful way resulting in unhelpful errors for the user
2299
+ if is_websocket {
2300
+ tracing::debug!("Upgrading client connection to WebSocket for error proxy");
2301
+ match hyper_tungstenite::upgrade(mock_req, None) {
2302
+ Ok((client_response, client_ws)) => {
2303
+ tracing::debug!("Client WebSocket upgrade for error proxy successful");
2304
+
2305
+ self.state.tasks.spawn(
2306
+ async move {
2307
+ let ws_handle = match WebSocketHandle::new(client_ws).await {
2308
+ Ok(ws_handle) => ws_handle,
2309
+ Err(err) => {
2310
+ tracing::debug!(
2311
+ ?err,
2312
+ "failed initiating websocket handle for error proxy"
2313
+ );
2314
+ return;
2315
+ }
2316
+ };
2317
+ let frame = err_to_close_frame(err, Some(request_ids.ray_id));
2318
+
2319
+ // Manual conversion to handle different tungstenite versions
2320
+ let code_num: u16 = frame.code.into();
2321
+ let reason = frame.reason.clone();
2322
+
2323
+ if let Err(err) = ws_handle
2324
+ .send(tokio_tungstenite::tungstenite::Message::Close(Some(
2325
+ tokio_tungstenite::tungstenite::protocol::CloseFrame {
2326
+ code: code_num.into(),
2327
+ reason,
2328
+ },
2329
+ )))
2330
+ .await
2331
+ {
2332
+ tracing::debug!(
2333
+ ?err,
2334
+ "failed sending websocket error proxy"
2335
+ );
2336
+ }
2337
+ }
2338
+ .instrument(
2339
+ tracing::info_span!("ws_error_proxy_task", ?request_ids.ray_id),
2340
+ ),
2341
+ );
2342
+
2343
+ // Return the response that will upgrade the client connection
2344
+ // For proper WebSocket handshaking, we need to preserve the original response
2345
+ // structure but convert it to our expected return type without modifying its content
2346
+ tracing::debug!(
2347
+ "Returning WebSocket upgrade response for error proxy to client"
2348
+ );
2349
+ // Extract the parts from the response but preserve all headers and status
2350
+ let (mut parts, _) = client_response.into_parts();
2351
+
2352
+ // Add Sec-WebSocket-Protocol header to the response
2353
+ // Many WebSocket clients (e.g. node-ws & Cloudflare) require a protocol in the response
2354
+ parts.headers.insert(
2355
+ "sec-websocket-protocol",
2356
+ hyper::header::HeaderValue::from_static("rivet"),
2357
+ );
2358
+
2359
+ // Create a new response with an empty body - WebSocket upgrades don't need a body
2360
+ Response::from_parts(
2361
+ parts,
2362
+ ResponseBody::Full(Full::<Bytes>::new(Bytes::new())),
2363
+ )
2364
+ }
2365
+ Err(err) => {
2366
+ tracing::error!(
2367
+ ?err,
2368
+ "Failed to upgrade client WebSocket for error proxy"
2369
+ );
2370
+
2371
+ err_into_response(
2372
+ errors::ConnectionError {
2373
+ error_message: format!(
2374
+ "Failed to upgrade client WebSocket for error proxy: {}",
2375
+ err
2376
+ ),
2377
+ remote_addr: self.remote_addr.to_string(),
2378
+ }
2379
+ .build(),
2380
+ )?
2381
+ }
2382
+ }
2383
+ } else {
2384
+ err_into_response(err)?
2385
+ }
2386
+ }
2387
+ };
2388
+
2389
+ if is_websocket && res.status() != StatusCode::SWITCHING_PROTOCOLS {
2390
+ tracing::debug!("returned non-101 response to websocket");
2391
+ }
2392
+
2393
+ // Add ray_id to response headers
2394
+ if let Ok(ray_id_value) = request_ids.ray_id.to_string().parse() {
2395
+ if let Some(existing_ray_id_value) = res
2396
+ .headers()
2397
+ .get(X_RIVET_RAY_ID)
2398
+ .and_then(|h| h.to_str().ok())
2399
+ {
2400
+ if ray_id_value != existing_ray_id_value {
2401
+ tracing::warn!(
2402
+ expected_ray_id=%request_ids.ray_id,
2403
+ received_ray_id=%existing_ray_id_value,
2404
+ "downstream service set ray id header to a different value",
2405
+ );
2406
+ }
2407
+ }
2408
+
2409
+ res.headers_mut().insert(X_RIVET_RAY_ID, ray_id_value);
2410
+ }
2411
+
2412
+ let status = res.status().as_u16();
2413
+
2414
+ // Update request context with response details
2415
+ request_context.guard_response_status = Some(status);
2416
+ request_context.service_response_status = Some(status);
2417
+
2418
+ if let Some(content_type) = res
2419
+ .headers()
2420
+ .get(hyper::header::CONTENT_TYPE)
2421
+ .and_then(|h| h.to_str().ok())
2422
+ {
2423
+ request_context.guard_response_content_type = Some(content_type.to_string());
2424
+ }
2425
+
2426
+ if let Some(expires) = res
2427
+ .headers()
2428
+ .get(hyper::header::EXPIRES)
2429
+ .and_then(|h| h.to_str().ok())
2430
+ {
2431
+ request_context.service_response_http_expires = Some(expires.to_string());
2432
+ }
2433
+
2434
+ if let Some(last_modified) = res
2435
+ .headers()
2436
+ .get(hyper::header::LAST_MODIFIED)
2437
+ .and_then(|h| h.to_str().ok())
2438
+ {
2439
+ request_context.service_response_http_last_modified = Some(last_modified.to_string());
2440
+ }
2441
+
2442
+ // Set timing information
2443
+ request_context.service_response_duration_ms =
2444
+ Some(start_time.elapsed().as_millis() as u32);
2445
+
2446
+ // Insert analytics event asynchronously
2447
+ let mut context_clone = request_context.clone();
2448
+ tokio::spawn(
2449
+ async move {
2450
+ if let Err(error) = context_clone.insert_event().await {
2451
+ tracing::warn!(?error, "failed to insert guard analytics event");
2452
+ }
2453
+ }
2454
+ .instrument(tracing::info_span!("insert_event_task")),
2455
+ );
2456
+
2457
+ let content_length = res
2458
+ .headers()
2459
+ .get(hyper::header::CONTENT_LENGTH)
2460
+ .and_then(|h| h.to_str().ok())
2461
+ .and_then(|s| s.parse::<usize>().ok())
2462
+ .unwrap_or(0);
2463
+
2464
+ // Log information about the completed request
2465
+ tracing::debug!(
2466
+ ?incoming_ray_id,
2467
+ ray_id=?request_ids.ray_id,
2468
+ req_id=?request_ids.req_id,
2469
+ method = %method,
2470
+ path = %path,
2471
+ host = %host,
2472
+ remote_addr = %self.remote_addr,
2473
+ status = %status,
2474
+ content_length = %content_length,
2475
+ "Request completed"
2476
+ );
2477
+
2478
+ Ok(res)
2479
+ }
2480
+ }
2481
+
2482
+ impl Clone for ProxyService {
2483
+ fn clone(&self) -> Self {
2484
+ Self {
2485
+ state: self.state.clone(),
2486
+ remote_addr: self.remote_addr,
2487
+ client: self.client.clone(),
2488
+ }
2489
+ }
2490
+ }
2491
+
2492
+ // Factory for creating proxy services
2493
+ pub struct ProxyServiceFactory {
2494
+ state: Arc<ProxyState>,
2495
+ }
2496
+
2497
+ impl ProxyServiceFactory {
2498
+ pub fn new(
2499
+ config: rivet_config::Config,
2500
+ routing_fn: RoutingFn,
2501
+ cache_key_fn: CacheKeyFn,
2502
+ middleware_fn: MiddlewareFn,
2503
+ port_type: PortType,
2504
+ clickhouse_inserter: Option<clickhouse_inserter::ClickHouseInserterHandle>,
2505
+ ) -> Self {
2506
+ let state = Arc::new(ProxyState::new(
2507
+ config,
2508
+ routing_fn,
2509
+ cache_key_fn,
2510
+ middleware_fn,
2511
+ port_type,
2512
+ clickhouse_inserter,
2513
+ ));
2514
+ Self { state }
2515
+ }
2516
+
2517
+ // Create a new proxy service for the given remote address
2518
+ pub fn create_service(&self, remote_addr: SocketAddr) -> ProxyService {
2519
+ ProxyService::new(self.state.clone(), remote_addr)
2520
+ }
2521
+
2522
+ pub async fn wait_idle(&self) {
2523
+ self.state.tasks.wait_idle().await
2524
+ }
2525
+ }
2526
+
2527
+ fn add_proxy_headers_with_addr(
2528
+ headers: &mut hyper::HeaderMap,
2529
+ original_headers: &hyper::HeaderMap,
2530
+ remote_addr: SocketAddr,
2531
+ ) -> Result<()> {
2532
+ // Copy headers except Host
2533
+ for (key, value) in original_headers.iter() {
2534
+ if key != hyper::header::HOST {
2535
+ headers.insert(key.clone(), value.clone());
2536
+ }
2537
+ }
2538
+
2539
+ // Add X-Forwarded-For header
2540
+ if let Some(existing) = original_headers.get(X_FORWARDED_FOR) {
2541
+ if let Ok(forwarded) = existing.to_str() {
2542
+ if !forwarded.contains(&remote_addr.ip().to_string()) {
2543
+ headers.insert(
2544
+ X_FORWARDED_FOR,
2545
+ hyper::header::HeaderValue::from_str(&format!(
2546
+ "{}, {}",
2547
+ forwarded,
2548
+ remote_addr.ip()
2549
+ ))?,
2550
+ );
2551
+ }
2552
+ }
2553
+ } else {
2554
+ headers.insert(
2555
+ X_FORWARDED_FOR,
2556
+ hyper::header::HeaderValue::from_str(&remote_addr.ip().to_string())?,
2557
+ );
2558
+ }
2559
+
2560
+ Ok(())
2561
+ }
2562
+
2563
+ fn err_into_response(err: anyhow::Error) -> Result<Response<ResponseBody>> {
2564
+ let (status, error_response) =
2565
+ if let Some(rivet_err) = err.chain().find_map(|x| x.downcast_ref::<RivetError>()) {
2566
+ let status = match (rivet_err.group(), rivet_err.code()) {
2567
+ ("api", "not_found") => StatusCode::NOT_FOUND,
2568
+ ("api", "unauthorized") => StatusCode::UNAUTHORIZED,
2569
+ ("api", "forbidden") => StatusCode::FORBIDDEN,
2570
+ ("guard", "rate_limit") => StatusCode::TOO_MANY_REQUESTS,
2571
+ ("guard", "upstream_error") => StatusCode::BAD_GATEWAY,
2572
+ ("guard", "routing_error") => StatusCode::BAD_GATEWAY,
2573
+ ("guard", "request_timeout") => StatusCode::GATEWAY_TIMEOUT,
2574
+ ("guard", "retry_attempts_exceeded") => StatusCode::BAD_GATEWAY,
2575
+ ("guard", "actor_not_found") => StatusCode::NOT_FOUND,
2576
+ ("guard", "actor_destroyed") => StatusCode::NOT_FOUND,
2577
+ ("guard", "service_unavailable") => StatusCode::SERVICE_UNAVAILABLE,
2578
+ ("guard", "actor_ready_timeout") => StatusCode::SERVICE_UNAVAILABLE,
2579
+ ("guard", "no_route") => StatusCode::NOT_FOUND,
2580
+ _ => StatusCode::BAD_REQUEST,
2581
+ };
2582
+
2583
+ (status, ErrorResponse::from(rivet_err))
2584
+ } else if let Some(raw_err) = err
2585
+ .chain()
2586
+ .find_map(|x| x.downcast_ref::<RawErrorResponse>())
2587
+ {
2588
+ (raw_err.0, raw_err.1.clone())
2589
+ } else {
2590
+ (
2591
+ StatusCode::INTERNAL_SERVER_ERROR,
2592
+ ErrorResponse::from(&RivetError {
2593
+ schema: &rivet_error::INTERNAL_ERROR,
2594
+ meta: None,
2595
+ message: None,
2596
+ }),
2597
+ )
2598
+ };
2599
+
2600
+ let body_json = serde_json::to_vec(&error_response)?;
2601
+ let bytes = Bytes::from(body_json);
2602
+
2603
+ Response::builder()
2604
+ .status(status)
2605
+ .header(hyper::header::CONTENT_TYPE, "application/json")
2606
+ .body(ResponseBody::Full(Full::new(bytes)))
2607
+ .map_err(Into::into)
2608
+ }
2609
+
2610
+ fn should_retry_request(res: &Result<Response<ResponseBody>>) -> bool {
2611
+ match res {
2612
+ Ok(resp) => should_retry_request_inner(resp.status(), resp.headers()),
2613
+ Err(err) => {
2614
+ if let Some(rivet_err) = err.chain().find_map(|x| x.downcast_ref::<RivetError>()) {
2615
+ rivet_err.group() == "guard" && rivet_err.code() == "service_unavailable"
2616
+ } else {
2617
+ false
2618
+ }
2619
+ }
2620
+ }
2621
+ }
2622
+
2623
+ // Determine if a response should trigger a retry: 503 + x-rivet-error
2624
+ fn should_retry_request_inner(status: StatusCode, headers: &hyper::HeaderMap) -> bool {
2625
+ status == StatusCode::SERVICE_UNAVAILABLE && headers.contains_key(X_RIVET_ERROR)
2626
+ }
2627
+
2628
+ // Determine if a websocket error is retryable (e.g., transient UPS/tunnel issues)
2629
+ fn is_retryable_ws_error(err: &anyhow::Error) -> bool {
2630
+ if let Some(rivet_err) = err.chain().find_map(|x| x.downcast_ref::<RivetError>()) {
2631
+ rivet_err.group() == "guard" && rivet_err.code() == "websocket_service_unavailable"
2632
+ } else {
2633
+ false
2634
+ }
2635
+ }
2636
+
2637
+ pub fn is_ws_hibernate(err: &anyhow::Error) -> bool {
2638
+ if let Some(rivet_err) = err.chain().find_map(|x| x.downcast_ref::<RivetError>()) {
2639
+ rivet_err.group() == "guard" && rivet_err.code() == "websocket_service_hibernate"
2640
+ } else {
2641
+ false
2642
+ }
2643
+ }
2644
+
2645
+ fn str_to_close_frame(err: &str) -> CloseFrame {
2646
+ // NOTE: reason cannot be more than 123 bytes as per the WS protocol spec
2647
+ let reason = rivet_util::safe_slice(err, 0, 123).into();
2648
+
2649
+ CloseFrame {
2650
+ code: CloseCode::Error,
2651
+ reason,
2652
+ }
2653
+ }
2654
+
2655
+ fn err_to_close_frame(err: anyhow::Error, ray_id: Option<Id>) -> CloseFrame {
2656
+ let rivet_err = err
2657
+ .chain()
2658
+ .find_map(|x| x.downcast_ref::<RivetError>())
2659
+ .cloned()
2660
+ .unwrap_or_else(|| RivetError::from(&INTERNAL_ERROR));
2661
+
2662
+ let code = match (rivet_err.group(), rivet_err.code()) {
2663
+ ("ws", "connection_closed") | ("ws", "eviction") => CloseCode::Normal,
2664
+ _ => CloseCode::Error,
2665
+ };
2666
+
2667
+ let reason = if let Some(ray_id) = ray_id {
2668
+ format!("{}.{}#{}", rivet_err.group(), rivet_err.code(), ray_id)
2669
+ } else {
2670
+ format!("{}.{}", rivet_err.group(), rivet_err.code())
2671
+ };
2672
+
2673
+ // NOTE: reason cannot be more than 123 bytes as per the WS protocol
2674
+ let reason = rivet_util::safe_slice(&reason, 0, 123).into();
2675
+
2676
+ CloseFrame { code, reason }
2677
+ }
2678
+
2679
+ fn to_hyper_close(frame: Option<CloseFrame>) -> hyper_tungstenite::tungstenite::Message {
2680
+ if let Some(frame) = frame {
2681
+ // Manual conversion to handle different tungstenite versions
2682
+ let code_num: u16 = frame.code.into();
2683
+ let reason = frame.reason.clone();
2684
+
2685
+ tokio_tungstenite::tungstenite::Message::Close(Some(
2686
+ tokio_tungstenite::tungstenite::protocol::CloseFrame {
2687
+ code: code_num.into(),
2688
+ reason,
2689
+ },
2690
+ ))
2691
+ } else {
2692
+ tokio_tungstenite::tungstenite::Message::Close(Some(
2693
+ tokio_tungstenite::tungstenite::protocol::CloseFrame {
2694
+ code: CloseCode::Normal,
2695
+ reason: "ws.closed".into(),
2696
+ },
2697
+ ))
2698
+ }
2699
+ }