* Tweaking the example to match what was demoed during the 9/21/2021 community call

* Added example CEL expressions
* Added link to 9/21/2021 community call youtube video
* Added section headers for the right nav
This commit is contained in:
Phil Kedy 2021-09-24 18:10:00 -04:00
parent ccc6ebd819
commit a927dd1028
1 changed files with 90 additions and 57 deletions

View File

@ -42,14 +42,14 @@ metadata:
name: myevent-subscription name: myevent-subscription
spec: spec:
pubsubname: pubsub pubsubname: pubsub
topic: transactions topic: inventory
routes: routes:
rules: rules:
- match: event.type == "withdraw.v3" - match: event.type == "widget"
path: /withdraw.v3 path: /widgets
- match: event.type == "withdraw.v2" - match: event.type == "gadget"
path: /withdraw.v2 path: /gadgets
default: /withdraw default: /products
scopes: scopes:
- app1 - app1
- app2 - app2
@ -77,24 +77,24 @@ def subscribe():
subscriptions = [ subscriptions = [
{ {
'pubsubname': 'pubsub', 'pubsubname': 'pubsub',
'topic': 'transactions', 'topic': 'inventory',
'routes': { 'routes': {
'rules': [ 'rules': [
{ {
'match': 'event.type == "withdraw.v3"', 'match': 'event.type == "widget"',
'path': '/withdraw.v3' 'path': '/widgets'
}, },
{ {
'match': 'event.type == "withdraw.v2"', 'match': 'event.type == "gadget"',
'path': '/withdraw.v2' 'path': '/gadgets'
}, },
], ],
'default': '/withdraw' 'default': '/products'
} }
}] }]
return jsonify(subscriptions) return jsonify(subscriptions)
@app.route('/withdraw', methods=['POST']) @app.route('/products', methods=['POST'])
def ds_subscriber(): def ds_subscriber():
print(request.json, flush=True) print(request.json, flush=True)
return json.dumps({'success':True}), 200, {'ContentType':'application/json'} return json.dumps({'success':True}), 200, {'ContentType':'application/json'}
@ -113,30 +113,30 @@ app.use(bodyParser.json({ type: 'application/*+json' }));
const port = 3000 const port = 3000
app.get('/dapr/subscribe', (req, res) => { app.get('/dapr/subscribe', (req, res) => {
res.json([ res.json([
{ {
pubsubname: "pubsub", pubsubname: "pubsub",
topic: "transactions", topic: "inventory",
routes: { routes: {
rules: [ rules: [
{ {
match: 'event.type == "withdraw.v3"', match: 'event.type == "widget"',
path: '/withdraw.v3' path: '/widgets'
}, },
{ {
match: 'event.type == "withdraw.v2"', match: 'event.type == "gadget"',
path: '/withdraw.v2' path: '/gadgets'
}, },
], ],
default: '/withdraw' default: '/products'
} }
} }
]); ]);
}) })
app.post('/withdraw', (req, res) => { app.post('/products', (req, res) => {
console.log(req.body); console.log(req.body);
res.sendStatus(200); res.sendStatus(200);
}); });
app.listen(port, () => console.log(`consumer app listening on port ${port}!`)) app.listen(port, () => console.log(`consumer app listening on port ${port}!`))
@ -145,25 +145,25 @@ app.listen(port, () => console.log(`consumer app listening on port ${port}!`))
{{% codetab %}} {{% codetab %}}
```csharp ```csharp
[Topic("pubsub", "transactions", "event.type ==\"withdraw.v3\"", 1)] [Topic("pubsub", "inventory", "event.type ==\"widget\"", 1)]
[HttpPost("withdraw.v3")] [HttpPost("widgets")]
public async Task<ActionResult<Account>> WithdrawV3(TransactionV3 transaction, [FromServices] DaprClient daprClient) public async Task<ActionResult<Account>> HandleWidget(Widget transaction, [FromServices] DaprClient daprClient)
{ {
// Logic // Logic
return account; return account;
} }
[Topic("pubsub", "transactions", "event.type ==\"withdraw.v2\"", 2)] [Topic("pubsub", "inventory", "event.type ==\"gadget\"", 2)]
[HttpPost("withdraw.v2")] [HttpPost("gadgets")]
public async Task<ActionResult<Account>> WithdrawV2(TransactionV2 transaction, [FromServices] DaprClient daprClient) public async Task<ActionResult<Account>> HandleGadget(Gadget transaction, [FromServices] DaprClient daprClient)
{ {
// Logic // Logic
return account; return account;
} }
[Topic("pubsub", "transactions")] [Topic("pubsub", "inventory")]
[HttpPost("withdraw")] [HttpPost("products")]
public async Task<ActionResult<Account>> Withdraw(Transaction transaction, [FromServices] DaprClient daprClient) public async Task<ActionResult<Account>> HandleProduct(Product transaction, [FromServices] DaprClient daprClient)
{ {
// Logic // Logic
return account; return account;
@ -208,19 +208,19 @@ func configureSubscribeHandler(w http.ResponseWriter, _ *http.Request) {
t := []subscription{ t := []subscription{
{ {
PubsubName: "pubsub", PubsubName: "pubsub",
Topic: "transactions", Topic: "inventory",
Routes: routes{ Routes: routes{
Rules: []rule{ Rules: []rule{
{ {
Match: `event.type == "withdraw.v3"`, Match: `event.type == "widget"`,
Path: "/withdraw.v3", Path: "/widgets",
}, },
{ {
Match: `event.type == "withdraw.v2"`, Match: `event.type == "gadget"`,
Path: "/withdraw.v2", Path: "/gadgets",
}, },
}, },
Default: "/withdraw", Default: "/products",
}, },
}, },
} }
@ -244,14 +244,14 @@ func main() {
require_once __DIR__.'/vendor/autoload.php'; require_once __DIR__.'/vendor/autoload.php';
$app = \Dapr\App::create(configure: fn(\DI\ContainerBuilder $builder) => $builder->addDefinitions(['dapr.subscriptions' => [ $app = \Dapr\App::create(configure: fn(\DI\ContainerBuilder $builder) => $builder->addDefinitions(['dapr.subscriptions' => [
new \Dapr\PubSub\Subscription(pubsubname: 'pubsub', topic: 'transactions', routes: ( new \Dapr\PubSub\Subscription(pubsubname: 'pubsub', topic: 'inventory', routes: (
rules: => [ rules: => [
('match': 'event.type == "withdraw.v3"', path: '/withdraw.v3'), ('match': 'event.type == "widget"', path: '/widgets'),
('match': 'event.type == "withdraw.v2"', path: '/withdraw.v2'), ('match': 'event.type == "gadget"', path: '/gadgets'),
] ]
default: '/withdraw')), default: '/products')),
]])); ]]));
$app->post('/withdraw', function( $app->post('/products', function(
#[\Dapr\Attributes\FromBody] #[\Dapr\Attributes\FromBody]
\Dapr\PubSub\CloudEvent $cloudEvent, \Dapr\PubSub\CloudEvent $cloudEvent,
\Psr\Log\LoggerInterface $logger \Psr\Log\LoggerInterface $logger
@ -266,7 +266,34 @@ $app->start();
{{< /tabs >}} {{< /tabs >}}
In these examples, depending on the type of the event (`event.type`), the application will be called on `/withdraw.v3`, `/withdraw.v2` or `/withdraw`. The expressions are written as [Common Expression Language (CEL)](https://opensource.google/projects/cel) where `event` represents the cloud event. Any of the attributes from the [CloudEvents core specification](https://github.com/cloudevents/spec/blob/v1.0.1/spec.md#required-attributes) can be referenced in the expression. ## Common Expression Language (CEL)
In these examples, depending on the type of the event (`event.type`), the application will be called on `/widgets`, `/gadgets` or `/products`. The expressions are written as [Common Expression Language (CEL)](https://github.com/google/cel-spec) where `event` represents the cloud event. Any of the attributes from the [CloudEvents core specification](https://github.com/cloudevents/spec/blob/v1.0.1/spec.md#required-attributes) can be referenced in the expression.
### Example expressions
Match "important" messages
```javascript
has(event.data.important) && event.data.important == true
```
Match deposits greater than $10000
```javascript
event.type == "deposit" && event.data.amount > 10000
```
Match multiple versions of a message
```javascript
event.type == "mymessage.v1"
```
```javascript
event.type == "mymessage.v2"
```
## CloudEvent attributes
For reference, the following attributes are from the CloudEvents specification. For reference, the following attributes are from the CloudEvents specification.
@ -476,7 +503,13 @@ Currently, comparisons to time (e.g. before or after "now") are not supported.
## Next steps ## Next steps
- Try the [Pub/Sub quickstart sample](https://github.com/dapr/quickstarts/tree/master/pub-sub) Watch [this video](https://www.youtube.com/watch?v=QqJgRmbH82I&t=1063s) on how to use message routing with pub/sub.
<p class="embed-responsive embed-responsive-16by9">
<iframe width="688" height="430" src="https://www.youtube.com/embed/QqJgRmbH82I?start=1063" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
</p>
- Try the [Pub/Sub routing sample](https://github.com/dapr/samples/tree/master/pub-sub-routing)
- Learn about [topic scoping]({{< ref pubsub-scopes.md >}}) - Learn about [topic scoping]({{< ref pubsub-scopes.md >}})
- Learn about [message time-to-live]({{< ref pubsub-message-ttl.md >}}) - Learn about [message time-to-live]({{< ref pubsub-message-ttl.md >}})
- Learn [how to configure Pub/Sub components with multiple namespaces]({{< ref pubsub-namespaces.md >}}) - Learn [how to configure Pub/Sub components with multiple namespaces]({{< ref pubsub-namespaces.md >}})