Skip to content

refactor(infinity-slack-bot): Embed the Slack bot dataflow - #112

Draft
akainth015 wants to merge 3 commits into
mainfrom
refactor/embedded-slack-dataflow
Draft

refactor(infinity-slack-bot): Embed the Slack bot dataflow#112
akainth015 wants to merge 3 commits into
mainfrom
refactor/embedded-slack-dataflow

Conversation

@akainth015

@akainth015 akainth015 commented Sep 1, 2026

Copy link
Copy Markdown
Member

This change allows us to ship a "boring" binary by using embedded mode to turn the dataflow in a Rust source file that we can reference from the CLI crate. Benefits are... minimal, but clean up the CLI output and because we don't need networking cleans up the deployment / usage story.

This PR is a draft because it's not ready for review; I've barely looked at or tested the code yet.

akainth015 and others added 3 commits August 31, 2026 18:49
…lit out `infinity-slack-dataflow`

Replaces the `sidecar_bidi` + deploy-backend architecture with Hydro's
embedded mode, per the two-crate design:

* **`infinity-slack-dataflow`** (new crate): the pure Hydro dataflow —
  `flow::slack_dataflow` plus the types (`slack::{SlackEvent, SlackAction}`,
  `daemon::{DaemonEvent, DaemonCommand}`) and shared state (`runtime`,
  `config`, `session_store`) its `q!()` closures reference. Carries the
  stageleft staging machinery (`gen_final` build script, `hydro_lang::setup!`)
  and the deterministic sim tests.
* **`infinity-slack-bot`**: now a plain CLI binary (canonical name
  `infinity-slack-bot`, no feature gates, no deploy machinery). Its
  `build.rs` compiles the dataflow with `generate_embedded` into a plain
  function returning a manually-driven DFIR graph; `main.rs` drives it on a
  `LocalSet` (`Dfir::run` + ctrl-c), wired to the former sidecars hoisted
  into ordinary tasks: `slack_io` (Socket Mode WebSocket + Web API executor)
  and `daemon_io`/`daemon_client` (per-thread Unix-socket daemon
  connections). Dataflow outputs are synchronous `FnMut` callbacks that hand
  off to the I/O tasks via unbounded channels (the callback cannot await;
  volume is human-scale chat traffic).

Embedded-mode constraints discovered and encoded in the dataflow crate:

* `q!()` bodies must reference crate items via imports, not `crate::...`
  paths (except path-qualified free functions): the include site re-expands
  quoted code in a foreign crate where `crate::` does not resolve.
* The CLI enables `hydro_lang/stageleft_macro_entrypoint` (forwarded through
  the dataflow crate) so `__staged` is emitted for the embedded include.

The dataflow itself is semantically unchanged: the sim tests moved over
as-is (only import paths updated), and a new integration test in the CLI
drives the *generated* embedded artifact end to end (SlackEvent in →
CreateSession out). `SlackClient::bot_user_id` was dropped (unread; already
logged at authentication).

BREAKING CHANGE: the bot is no longer started via Hydro deploy
(`cargo run --example deploy`); run the `infinity-slack-bot` binary
directly (`cargo run -p infinity-slack-bot` or `cargo install`). Library
consumers: `infinity_slack_bot::{flow,sidecar,daemon_sidecar,...}` moved to
`infinity_slack_dataflow::{flow,slack,daemon,runtime,config,session_store}`.
…ad of zombifying

* Validate `bot_token` (`auth.test`) and `app_token` (`apps.connections.open`)
  on the startup path, so a bad token exits with an actionable error instead
  of panicking a detached tokio task (whose panic is isolated, leaving the
  bot running but permanently unable to execute Slack actions).
* Watch the Slack I/O task handles in the main `select!` so any future task
  death tears the process down instead of zombifying.
* Reuse the startup-validated Socket Mode URL for the first connection.
…de stack

* **Stale "sidecar" references removed**: `runtime.rs` module/`init` doc comments now say the runtime is initialized by the bot binary at startup; log messages in `daemon_io.rs` ("daemon I/O task received command") and `slack_io.rs` ("stopping Slack inbound task") updated; `dataflow_sim.rs` module docs now say "no I/O tasks are run". Also fixed two "the CLI wraps" → "the bot wraps" doc mentions for consistency.
* **`flow.rs` NOTE clarified**: explains that stageleft rewrites *expression* paths through the staged module (verified in generated output: `crate::runtime::get()` becomes `infinity_slack_dataflow::__staged::runtime::get()`), while paths in *type* position are pasted verbatim into the foreign include site and must therefore be imported.
* **`init_tracing` no longer panics**: returns `Result<(), BoxError>` when the log file can't be opened; `main` prints the error to stderr (tracing isn't up yet) and exits with `ExitCode::FAILURE`.
* **Daemon dispatch task is now monitored**: `daemon_io::spawn` returns a `DaemonIo` struct (symmetric with `SlackIo`) that includes the command-dispatch task's `JoinHandle`, and `main`'s `select!` now treats its completion as fatal — a panicked dispatch task can no longer leave a zombie bot silently dropping commands.
* **"unexpected" label corrected**: `io_task_exited`'s clean-exit message is now "exited; the bot cannot run without it" (fatal, but not mislabeled as unexpected), and the `SlackIo::inbound` doc contract notes the one legitimate clean-exit path (dataflow-side channel closed — only possible once the dataflow is gone, so still fatal).

Verified: `cargo fmt --all --check` clean, `cargo clippy --all-targets -D warnings` on both crates clean, all 35 tests pass (19 bot unit + 10 dataflow unit + 6 sim). Committed on the sandbox bookmark on top of `refactor/embedded-slack-dataflow` with a conventional-commit message.

Co-authored-by: Infinity 🤖 <infinity@hydro.run>
@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Sep 1, 2026

Copy link
Copy Markdown

Deploying infinity with  Cloudflare Pages  Cloudflare Pages

Latest commit: c9ec7c7
Status: ✅  Deploy successful!
Preview URL: https://e4718216.infinity-dc7.pages.dev
Branch Preview URL: https://refactor-embedded-slack-data.infinity-dc7.pages.dev

View logs

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant