feat(cli): Add worker CLI with configurable options#760
Conversation
Add a taskbroker_client CLI exposing `worker` (pull) and `push_worker` (push) commands, each with a click option for every TaskWorker / PushTaskWorker constructor argument, plus `spawn` and `scheduler` helpers. Add `--grpc-max-message-size` to `push_worker`, threaded through PushTaskWorker as a new `grpc_max_message_size` argument that falls back to the TASKBROKER_GRPC_MAX_MESSAGE_SIZE env var when unset. Add `--track-producer-futures/--no-track-producer-futures` to both worker commands, which sets the ARROYO_TRACK_PRODUCER_FUTURES env var arroyo reads to toggle producer future tracking. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
oh wait. can we have one cli for push/non-push? otherwise i think we might have a hard time unifying the templates too (each app will need to configure where the push cli is mounted, and where the non-push cli is mounted)
or a click group for push/non-push CLIs, and apps attack the click group to their main group
What do you mean by this? Isn't that what they can already do with the |
right now there are two entrypoints for taskworker CLI that can be mounted in the application's CLI in different places. it is permitted to do this, though a bad idea: it would be more restrictive, and less boilerplate in applcation code if instead only one CLI needs to be mounted. could be: or: in the ops repo template, one then only has to configure |
|
@untitaker I think I see your point, but I deliberately separated them because they require different arguments. If I had one command |
yeah i see that. but you can make them sub-commands of a |
Combine the standalone `worker` and `push_worker` commands into a single `worker` click group with `pull` and `push` subcommands, so it composes into the app's command tree (e.g. `sentry run worker pull` / `worker push`). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit bf572dd. Configure here.
| ) -> None: | ||
| from taskbroker_client.worker import TaskWorker | ||
|
|
||
| os.environ["ARROYO_TRACK_PRODUCER_FUTURES"] = str(track_producer_futures) |
There was a problem hiding this comment.
Track futures flag overwrites env
Medium Severity
Both pull and push always assign ARROYO_TRACK_PRODUCER_FUTURES from the Click flag, whose default is false. Deployments that enable tracking only via the environment lose that setting when the new worker commands run without --track-producer-futures, unlike --grpc-max-message-size, which leaves the env var in effect when unset.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit bf572dd. Configure here.
| exitcode = worker.start() | ||
| raise SystemExit(exitcode) |
There was a problem hiding this comment.
Bug: The pull command worker incorrectly re-raises KeyboardInterrupt on graceful shutdown, causing a non-zero exit code instead of a clean exit with code 0.
Severity: HIGH
Suggested Fix
Modify TaskWorker.start() to catch the KeyboardInterrupt and allow the function to complete and return an exit code, similar to how PushTaskWorker.start() is implemented. This will prevent the exception from propagating and ensure the CLI can call SystemExit(0) for a clean shutdown.
Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent. Verify if this is a real issue. If it is, propose a fix; if not, explain why it's
not valid.
Location: clients/python/src/taskbroker_client/cli.py#L210-L211
Potential issue: When the `pull` command worker receives a `SIGINT` or `SIGTERM` signal
for a graceful shutdown, the underlying `TaskWorker.start()` method re-raises a
`KeyboardInterrupt` after handling the signal. This unhandled exception propagates up,
preventing the CLI from executing `raise SystemExit(exitcode)`. Instead, the process
terminates with a non-zero exit code (e.g., 130), incorrectly signaling a crash to
orchestration systems like Kubernetes. The `push` command worker correctly swallows this
exception and exits cleanly with code 0.


Summary
Adds a
taskbroker_clientCLI for running workers, with aclickoption for every constructor argument ofTaskWorkerandPushTaskWorker.worker— runs a pull-modeTaskWorker, with an option for eachTaskWorker.__init__argument.push_worker— runs a push-modePushTaskWorker, with an option for eachPushTaskWorker.__init__argument.spawn/scheduler— existing example helpers.New tunables
--grpc-max-message-size(onpush_worker): threaded through a newgrpc_max_message_sizeargument onPushTaskWorker. When unset, the worker falls back to theTASKBROKER_GRPC_MAX_MESSAGE_SIZEenv var, so existing env-based deployment config keeps working.--track-producer-futures/--no-track-producer-futures(on both commands): arroyo only readsARROYO_TRACK_PRODUCER_FUTURESfrom the environment, so the command sets that env var from the flag before starting the worker. It's on both commands because the future-tracking producer runs in child processes for both pull and push modes.Test plan
black,isort,flake8, andmypypass via pre-commit.True → "True"enables,False → "False"disables).🤖 Generated with Claude Code