From outside your app
"External" to a Reboot application means from a (micro)service (e.g., a gRPC or HTTP based service) or a lambda (e.g., using some serverless framework), or even from your laptop! Your tests are another example of "external".
In order to call a method on an instance of your state externally,
you'll need to use an ExternalContext, for example:
- Python
- TypeScript
from reboot.aio.external import ExternalContext
context = ExternalContext(
name="send message",
url="http://localhost:9991"
)
chat_room = ChatRoom.ref(id)
response = await chat_room.send(context, message="Hello, World!")
import { ExternalContext } from "@reboot-dev/reboot";
const context = new ExternalContext({
name: "send message",
url: "http://localhost:9991"
});
const chat_room = ChatRoom.ref(id);
const response = await chat_room.send(context, { message: "Hello, World!" });
The url argument specifies where your Reboot application is
running, e.g., on your laptop via rbt dev, in a container on
Kubernetes via rbt serve (where url will likely route to your
Kubernetes gateway), or in the cloud via rbt cloud.
Because an ExternalContext is used outside of Reboot, a series of
Reboot methods called using an ExternalContext don't have any
atomicity guarantees with regard to one another (although the
individual methods executing within Reboot will of course still have
their own atomicity). If you are calling multiple Reboot methods that
you would like to happen atomically, you can move those calls into a
transaction, and then
call that method from your client.
Making calls idempotently
You can make calls idempotently()
using an ExternalContext so
that you only perform operations once. You can even pass an
idempotency seed, e.g., a UUID, to an ExternalContext when
constructing it so that every time you re-run code using that
ExternalContext it will generate the same idempotency keys so that
your external code will execute "where it left off" from the last time
it was running. This is similar to trying to write code that
idempotently
converges,
just external to your Reboot application. Here's an example:
- Python
- TypeScript
context = ExternalContext(
name="send message",
url="http://localhost:9991",
idempotency_seed=uuid.UUID("123e4567-e89b-12d3-a456-426614174000"),
)
const context = new ExternalContext({
name: "send message",
url: "http://localhost:9991",
idempotencySeed="123e4567-e89b-12d3-a456-426614174000",
});
Calling readers reactively
Using an ExternalContext, you can also call reader methods
reactively: you receive a new response every time the state
changes. For example:
- Python
- TypeScript
fig = Fig.ref(fig_id)
async for response in fig.reactively().get_position(context):
print(f"{fig_id}: {response}")
// COMING SOON!
Making concurrent calls
When calling multiple Reboot methods externally, you can use the
same concurrency patterns described in
Making concurrent calls.
For Python, the concurrently helper provides adaptive
concurrency limits and streaming results — see
concurrently (Python)
for details and examples.