13
13
Python package to develop applications with the Dispatch platform.
14
14
15
15
[ fastapi ] : https://fastapi.tiangolo.com/tutorial/first-steps/
16
- [ ngrok ] : https://ngrok.com/
17
16
[ pypi ] : https://pypi.org/project/dispatch-py/
18
17
[ signup ] : https://console.dispatch.run/
19
18
20
19
- [ What is Dispatch?] ( #what-is-dispatch )
21
20
- [ Installation] ( #installation )
21
+ - [ Installing the Dispatch CLI] ( #installing-the-dispatch-cli )
22
+ - [ Installing the Dispatch SDK] ( #installing-the-dispatch-sdk )
22
23
- [ 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 )
24
27
- [ Integration with FastAPI] ( #integration-with-fastapi )
25
- - [ Local Testing] ( #local-testing )
26
- - [ Distributed Coroutines for Python] ( #distributed-coroutines-for-python )
28
+ - [ Configuration] ( #configuration )
27
29
- [ Serialization] ( #serialization )
28
30
- [ Examples] ( #examples )
29
31
- [ Contributing] ( #contributing )
@@ -32,166 +34,75 @@ Python package to develop applications with the Dispatch platform.
32
34
33
35
Dispatch is a platform for developing scalable & reliable distributed systems.
34
36
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
-
43
37
To get started, follow the instructions to [ sign up for Dispatch] [ signup ] 🚀.
44
38
45
39
## Installation
46
40
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
53
42
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/ ) :
56
46
57
- ``` python
58
- @dispatch.function
59
- def action (msg ):
60
- ...
47
+ ``` console
48
+ brew tap stealthrocket/dispatch
49
+ brew install dispatch
61
50
```
62
51
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.
67
54
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.*
74
59
75
- ### Configuration
60
+ ### Installing the Dispatch SDK
76
61
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
+ ```
84
66
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
90
68
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
95
70
96
- ### Integration with FastAPI
71
+ The following snippet shows how to write a very simple Dispatch application
72
+ that does the following:
97
73
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
100
77
101
78
``` 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
108
81
109
82
@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} ! " )
113
85
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' ))
118
87
```
119
88
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.
126
91
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
135
93
94
+ The simplest way to run a Dispatch application is to use the Dispatch CLI, first
95
+ we need to login:
136
96
``` console
137
- python -m dispatch.test $DISPATCH_ENDPOINT_URL
97
+ dispatch login
138
98
```
139
99
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:
146
101
``` 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
172
103
```
173
- Running this command opens a terminal interface that looks like this:
174
- ```
175
- ngrok
176
104
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
195
106
196
107
The ` @dispatch.function ` decorator can also be applied to Python coroutines
197
108
(a.k.a. * async* functions), in which case each ` await ` point becomes a
@@ -243,11 +154,67 @@ async def transform(msg):
243
154
```
244
155
245
156
Dispatch 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-----... ` |
247
214
248
215
### Serialization
249
216
250
- Dispatch uses the [ pickle] library to serialize coroutines.
217
+ Dispatch uses the [ pickle] [ pickle ] library to serialize coroutines.
251
218
252
219
[ pickle ] : https://docs.python.org/3/library/pickle.html
253
220
@@ -266,7 +233,6 @@ For help with a serialization issues, please submit a [GitHub issue][issues].
266
233
267
234
[ issues ] : https://github.com/stealthrocket/dispatch-py/issues
268
235
269
-
270
236
## Examples
271
237
272
238
Check out the [ examples] ( examples/ ) directory for code samples to help you get
0 commit comments