1313Python package to develop applications with the Dispatch platform.
1414
1515[ fastapi ] : https://fastapi.tiangolo.com/tutorial/first-steps/
16- [ ngrok ] : https://ngrok.com/
1716[ pypi ] : https://pypi.org/project/dispatch-py/
1817[ signup ] : https://console.dispatch.run/
1918
2019- [ What is Dispatch?] ( #what-is-dispatch )
2120- [ Installation] ( #installation )
21+ - [ Installing the Dispatch CLI] ( #installing-the-dispatch-cli )
22+ - [ Installing the Dispatch SDK] ( #installing-the-dispatch-sdk )
2223- [ Usage] ( #usage )
23- - [ Configuration] ( #configuration )
24+ - [ Writing Dispatch Applications] ( #writing-dispatch-applications )
25+ - [ Running Dispatch Applications] ( #running-dispatch-applications )
26+ - [ Writing Transactional Applications with Dispatch] ( #writing-transactional-applications-with-dispatch )
2427 - [ Integration with FastAPI] ( #integration-with-fastapi )
25- - [ Local Testing] ( #local-testing )
26- - [ Distributed Coroutines for Python] ( #distributed-coroutines-for-python )
28+ - [ Configuration] ( #configuration )
2729 - [ Serialization] ( #serialization )
2830- [ Examples] ( #examples )
2931- [ Contributing] ( #contributing )
@@ -32,166 +34,75 @@ Python package to develop applications with the Dispatch platform.
3234
3335Dispatch is a platform for developing scalable & reliable distributed systems.
3436
35- Dispatch provides a simple programming model based on * Distributed Coroutines* ,
36- allowing complex, dynamic workflows to be expressed with regular code and
37- control flow.
38-
39- Dispatch schedules function calls across a fleet of service instances,
40- incorporating ** fair scheduling** , transparent ** retry of failed operations** ,
41- and ** durability** .
42-
4337To get started, follow the instructions to [ sign up for Dispatch] [ signup ] 🚀.
4438
4539## Installation
4640
47- This package is published on [ PyPI] [ pypi ] as ** dispatch-py** , to install:
48- ``` sh
49- pip install dispatch-py
50- ```
51-
52- ## Usage
41+ ### Installing the Dispatch CLI
5342
54- The SDK allows Python applications to declare functions that Dispatch can
55- orchestrate:
43+ As a pre-requisite, we recommend installing the Dispatch CLI to simplify the
44+ configuration and execution of applications that use Dispatch. On macOS, this
45+ can be done easily using [ Homebrew] ( https://docs.brew.sh/ ) :
5646
57- ``` python
58- @dispatch.function
59- def action (msg ):
60- ...
47+ ``` console
48+ brew tap stealthrocket/dispatch
49+ brew install dispatch
6150```
6251
63- The ** @dispatch .function** decorator declares a function that can be run by
64- Dispatch. The call has durable execution semantics; if the function fails
65- with a temporary error, it is automatically retried, even if the program is
66- restarted, or if multiple instances are deployed.
52+ Alternatively, you can download the latest ` dispatch ` binary from the
53+ [ Releases] ( https://github.com/stealthrocket/dispatch/releases ) page.
6754
68- The SDK adds a method to the ` action ` object, allowing the program to
69- dispatch an asynchronous invocation of the function; for example:
70-
71- ``` python
72- action.dispatch(' hello' )
73- ```
55+ * Note that this step is optional, applications that use Dispatch can run without
56+ the CLI, passing configuration through environment variables or directly in the
57+ code. However, the CLI automates the onboarding flow and simplifies the
58+ configuration, so we recommend starting with it.*
7459
75- ### Configuration
60+ ### Installing the Dispatch SDK
7661
77- In order for Dispatch to interact with functions remotely, the SDK needs to be
78- configured with the address at which the server can be reached. The Dispatch
79- API Key must also be set, and optionally, a public signing key should be
80- configured to verify that requests originated from Dispatch. These
81- configuration options can be passed as arguments to the
82- the ` Dispatch ` constructor, but by default they will be loaded from environment
83- variables:
62+ The Python package is published on [ PyPI] [ pypi ] as ** dispatch-py** , to install:
63+ ``` console
64+ pip install dispatch-py
65+ ```
8466
85- | Environment Variable | Value Example |
86- | :-------------------------- | :--------------------------------- |
87- | ` DISPATCH_API_KEY ` | ` d4caSl21a5wdx5AxMjdaMeWehaIyXVnN ` |
88- | ` DISPATCH_ENDPOINT_URL ` | ` https://service.domain.com ` |
89- | ` DISPATCH_VERIFICATION_KEY ` | ` -----BEGIN PUBLIC KEY-----... ` |
67+ ## Usage
9068
91- Finally, the ` Dispatch ` instance needs to mount a route on a HTTP server in to
92- receive requests from Dispatch. At this time, the SDK integrates with
93- FastAPI; adapters for other popular Python frameworks will be added in the
94- future.
69+ ### Writing Dispatch Applications
9570
96- ### Integration with FastAPI
71+ The following snippet shows how to write a very simple Dispatch application
72+ that does the following:
9773
98- The following code snippet is a complete example showing how to install a
99- ` Dispatch ` instance on a [ FastAPI] [ fastapi ] server:
74+ 1 . declare a dispatch function named ` greet ` which can run asynchronously
75+ 2 . schedule a call to ` greet ` with the argument ` World `
76+ 3 . run until all dispatched calls have completed
10077
10178``` python
102- from fastapi import FastAPI
103- from dispatch.fastapi import Dispatch
104- import requests
105-
106- app = FastAPI()
107- dispatch = Dispatch(app)
79+ # main.py
80+ import dispatch
10881
10982@dispatch.function
110- def publish (url , payload ):
111- r = requests.post(url, data = payload)
112- r.raise_for_status()
83+ def greet (msg : str ):
84+ print (f " Hello, $ { msg} ! " )
11385
114- @app.get (' /' )
115- def root ():
116- publish.dispatch(' https://httpstat.us/200' , {' hello' : ' world' })
117- return {' answer' : 42 }
86+ dispatch.run(lambda : greet.dispatch(' World' ))
11887```
11988
120- In this example, GET requests on the HTTP server dispatch calls to the
121- ` publish ` function. The function runs concurrently to the rest of the
122- program, driven by the Dispatch SDK.
123-
124- The instantiation of the ` Dispatch ` object on the ` FastAPI ` application
125- automatically installs the HTTP route needed for Dispatch to invoke functions.
89+ Obviously, this is just an example, a real application would perform much more
90+ interesting work, but it's a good start to get a sense of how to use Dispatch.
12691
127- ### Local Testing
128-
129- #### Mock Dispatch
130-
131- The SDK ships with a mock Dispatch server. It can be used to quickly test your
132- local functions, without requiring internet access.
133-
134- Note that the mock Dispatch server has very limited scheduling capabilities.
92+ ### Running Dispatch Applications
13593
94+ The simplest way to run a Dispatch application is to use the Dispatch CLI, first
95+ we need to login:
13696``` console
137- python -m dispatch.test $DISPATCH_ENDPOINT_URL
97+ dispatch login
13898```
13999
140- The command will start a mock Dispatch server and print the configuration
141- for the SDK.
142-
143- For example, if your functions were exposed through a local endpoint
144- listening on ` http://127.0.0.1:8000 ` , you could run:
145-
100+ Then we are ready to run the example program we wrote above:
146101``` console
147- $ python -m dispatch.test http://127.0.0.1:8000
148- Spawned a mock Dispatch server on 127.0.0.1:4450
149-
150- Dispatching function calls to the endpoint at http://127.0.0.1:8000
151-
152- The Dispatch SDK can be configured with:
153-
154- export DISPATCH_API_URL="http://127.0.0.1:4450"
155- export DISPATCH_API_KEY="test"
156- export DISPATCH_ENDPOINT_URL="http://127.0.0.1:8000"
157- export DISPATCH_VERIFICATION_KEY="Z+nTe2VRcw8t8Ihx++D+nXtbO28nwjWIOTLRgzrelYs="
158- ```
159-
160- #### Real Dispatch
161-
162- To test local functions with the production instance of Dispatch, it needs
163- to be able to access your local endpoint.
164-
165- A common approach consists of using [ ngrok] [ ngrok ] to setup a public endpoint
166- that forwards to the server running on localhost.
167-
168- For example, assuming the server is running on port 8000 (which is the default
169- with FastAPI), the command to create a ngrok tunnel is:
170- ``` sh
171- ngrok http http://localhost:8000
102+ dispatch run -- python3 main.py
172103```
173- Running this command opens a terminal interface that looks like this:
174- ```
175- ngrok
176104
177- Build better APIs with ngrok. Early access: ngrok.com/early-access
178-
179- Session Status online
180- Account Alice (Plan: Free)
181- Version 3.6.0
182- Region United States (California) (us-cal-1)
183- Latency -
184- Web Interface http://127.0.0.1:4040
185- Forwarding https://f441-2600-1700-2802-e01f-6861-dbc9-d551-ecfb.ngrok-free.app -> http://localhost:8000
186- ```
187- To configure the Dispatch SDK, set the endpoint URL to the endpoint for the
188- ** Forwarding** parameter; each ngrok instance is unique, so you would have a
189- different value, but in this example it would be:
190- ``` sh
191- export DISPATCH_ENDPOINT_URL=" https://f441-2600-1700-2802-e01f-6861-dbc9-d551-ecfb.ngrok-free.app"
192- ```
193-
194- ### Distributed Coroutines for Python
105+ ### Writing Transactional Applications with Dispatch
195106
196107The ` @dispatch.function ` decorator can also be applied to Python coroutines
197108(a.k.a. * async* functions), in which case each ` await ` point becomes a
@@ -243,11 +154,67 @@ async def transform(msg):
243154```
244155
245156Dispatch converts Python coroutines to * Distributed Coroutines* , which can be
246- suspended and resumed on any instance of a service across a fleet.
157+ suspended and resumed on any instance of a service across a fleet. For a deep
158+ dive on these concepts, read our blog post on
159+ [ * Distributed Coroutines with a Native Python Extension and Dispatch* ] ( https://stealthrocket.tech/blog/distributed-coroutines-in-python ) .
160+
161+ ### Integration with FastAPI
162+
163+ Many web applications written in Python are developed using [ FastAPI] [ fastapi ] .
164+ Dispatch can integrate with these applications by instantiating a
165+ ` dispatch.fastapi.Dispatch ` object. When doing so, the Dispatch functions
166+ declared by the program can be invoked remotely over the same HTTP interface
167+ used for the [ FastAPI] [ fastapi ] handlers.
168+
169+ The following code snippet is a complete example showing how to install a
170+ ` Dispatch ` instance on a [ FastAPI] [ fastapi ] server:
171+
172+ ``` python
173+ from fastapi import FastAPI
174+ from dispatch.fastapi import Dispatch
175+ import requests
176+
177+ app = FastAPI()
178+ dispatch = Dispatch(app)
179+
180+ @dispatch.function
181+ def publish (url , payload ):
182+ r = requests.post(url, data = payload)
183+ r.raise_for_status()
184+
185+ @app.get (' /' )
186+ def root ():
187+ publish.dispatch(' https://httpstat.us/200' , {' hello' : ' world' })
188+ return {' answer' : 42 }
189+ ```
190+
191+ In this example, GET requests on the HTTP server dispatch calls to the
192+ ` publish ` function. The function runs concurrently to the rest of the
193+ program, driven by the Dispatch SDK.
194+
195+ ### Configuration
196+
197+ The Dispatch CLI automatically configures the SDK, so manual configuration is
198+ usually not required when running Dispatch applications. However, in some
199+ advanced cases, it might be useful to explicitly set configuration options.
200+
201+ In order for Dispatch to interact with functions remotely, the SDK needs to be
202+ configured with the address at which the server can be reached. The Dispatch
203+ API Key must also be set, and optionally, a public signing key should be
204+ configured to verify that requests originated from Dispatch. These
205+ configuration options can be passed as arguments to the
206+ the ` Dispatch ` constructor, but by default they will be loaded from environment
207+ variables:
208+
209+ | Environment Variable | Value Example |
210+ | :-------------------------- | :--------------------------------- |
211+ | ` DISPATCH_API_KEY ` | ` d4caSl21a5wdx5AxMjdaMeWehaIyXVnN ` |
212+ | ` DISPATCH_ENDPOINT_URL ` | ` https://service.domain.com ` |
213+ | ` DISPATCH_VERIFICATION_KEY ` | ` -----BEGIN PUBLIC KEY-----... ` |
247214
248215### Serialization
249216
250- Dispatch uses the [ pickle] library to serialize coroutines.
217+ Dispatch uses the [ pickle] [ pickle ] library to serialize coroutines.
251218
252219[ pickle ] : https://docs.python.org/3/library/pickle.html
253220
@@ -266,7 +233,6 @@ For help with a serialization issues, please submit a [GitHub issue][issues].
266233
267234[ issues ] : https://github.com/stealthrocket/dispatch-py/issues
268235
269-
270236## Examples
271237
272238Check out the [ examples] ( examples/ ) directory for code samples to help you get
0 commit comments