|
2 | 2 | # Redis Extension for Azure Functions
|
3 | 3 |
|
4 | 4 | ## Introduction
|
| 5 | +This repository contains the triggers and bindings to use in your [Azure Functions](https://learn.microsoft.com/azure/azure-functions/functions-get-started) and [WebJobs](https://learn.microsoft.com/azure/app-service/webjobs-sdk-how-to). |
| 6 | +There are three triggers in the Azure Functions Redis Extension: |
| 7 | +- `RedisPubSubTrigger` triggers on [Redis pubsub messages](https://redis.io/docs/manual/pubsub/) |
| 8 | +- `RedisListsTrigger` triggers on [Redis lists](https://redis.io/docs/data-types/lists/) |
| 9 | +- `RedisStreamsTrigger` triggers on [Redis streams](https://redis.io/docs/data-types/streams/) |
5 | 10 |
|
6 |
| -This repository contains the Redis trigger bindings to use in your [Azure Functions](https://learn.microsoft.com/azure/azure-functions/functions-get-started) and [WebJobs](https://learn.microsoft.com/azure/app-service/webjobs-sdk-how-to). The trigger binding enables invoking a function when message is received on a [Redis PubSub channel](https://redis.io/docs/manual/pubsub/) or on a [KeySpace or KeyEvent Notification](https://redis.io/docs/manual/keyspace-notifications/). |
| 11 | +## Getting Started |
| 12 | +1. [Set up an Azure Cache for Redis instance](https://learn.microsoft.com/azure/azure-cache-for-redis/quickstart-create-redis) or [install Redis locally](https://redis.io/download/). |
| 13 | +1. Install the [Azure Functions Core Tools](https://learn.microsoft.com/azure/azure-functions/functions-run-local). |
| 14 | +1. Create a function project for .NET: |
| 15 | + ```cmd |
| 16 | + mkdir RedisFunctions |
| 17 | + cd RedisFunctions |
| 18 | + func init --worker-runtime dotnet |
| 19 | + ``` |
| 20 | +1. Install the Redis Extension using `dotnet add package Microsoft.Azure.WebJobs.Extensions.Redis --prerelease`. |
| 21 | +For private preview, these are the following steps to add the nuget package to your project: |
| 22 | + 1. Create a `NuGet.Config` file in the project folder (`RedisFunctions` in the above step): |
| 23 | + ``` |
| 24 | + <?xml version="1.0" encoding="utf-8"?> |
| 25 | + <configuration> |
| 26 | + <packageSources> |
| 27 | + <add key="local-packages" value="./local-packages" /> |
| 28 | + </packageSources> |
| 29 | + </configuration> |
| 30 | + ``` |
| 31 | + 1. Add the following line to the `<PropertyGroup>` section of the csproj. |
| 32 | + ``` |
| 33 | + <RestoreSources>$(RestoreSources);./local-packages;https://api.nuget.org/v3/index.json</RestoreSources> |
| 34 | + ``` |
| 35 | + 1. Create a folder `local-packages` within the project folder, and download the latest NuGet package from [GitHub Releases](https://github.com/Azure/azure-functions-redis-extension/releases) to this `local-packages` folder. |
| 36 | + 1. Install the package: |
| 37 | + ``` |
| 38 | + dotnet add package Microsoft.Azure.WebJobs.Extensions.Redis --prerelease |
| 39 | + dotnet restore |
| 40 | + ``` |
7 | 41 |
|
8 |
| -The Azure Functions Redis Extension allows you to trigger functions based on Redis pub/sub messages, Redis Keyspace notifications, and Redis Keyevent notifications from your Azure Redis Cache all via the [Azure functions interface](https://docs.microsoft.com/azure/azure-functions/functions-create-your-first-function-visual-studio). |
| 42 | +## Usage |
| 43 | +### `RedisPubSubTrigger` |
| 44 | +The `RedisPubSubTrigger` subscribes to a specific channel pattern using [`PSUBSCRIBE`](https://redis.io/commands/psubscribe/), and surfaces messages received on those channels to the function. |
9 | 45 |
|
10 |
| -To get started with developing with this extension, make sure you first [set up an Azure Cache for Redis instance](https://docs.microsoft.com/azure/azure-cache-for-redis/quickstart-create-redis). Then you can go ahead and begin developing your functions. |
| 46 | +> **Warning** |
| 47 | +> This trigger is not fully supported on a [Consumption plan](https://learn.microsoft.com/azure/azure-functions/consumption-plan) because Redis PubSub requires clients to always be actively listening to receive all messages. |
| 48 | +> For consumption plans, there is a chance your function may miss certain messages published to the channel. Functions with this trigger shuld also not be scaled out. |
11 | 49 |
|
12 |
| -## Usage |
13 |
| -### RedisTrigger Parameters |
14 |
| -Input: RedisTrigger takes in three arguments: |
15 |
| -- `ConnectionString`: connection string to the redis cache (eg `<cacheName>.redis.cache.windows.net:6380,password=...`) |
16 |
| -- `TriggerType`: This is an `RedisTriggerType` enum that can be one of three values: `PubSub`, `KeySpace`, or `KeyEvent` |
17 |
| -- `Trigger`: |
18 |
| - - If `TriggerType` is `PubSub`, this is the name of the pubsub channel on which to trigger |
19 |
| - - If `TriggerType` is `KeySpace`, this is the key on which to trigger |
20 |
| - - If `TriggerType` is `KeyEvent`, this is the keyevent on which to trigger |
21 |
| - |
22 |
| -The RedisTrigger returns a `RedisMessageModel` object that has three fields: |
| 50 | +> **Note** |
| 51 | +> In general, functions with this the `RedisPubSubTrigger` should not be scaled out to multiple instances. |
| 52 | +> Each instance will listen and process each pubsub message, resulting in duplicate processing. |
| 53 | +
|
| 54 | +#### Inputs |
| 55 | +- `ConnectionString`: connection string to the redis cache (eg `<cacheName>.redis.cache.windows.net:6380,password=...`). |
| 56 | +- `Channel`: name of the pubsub channel that the trigger should listen to. |
| 57 | +
|
| 58 | +#### Sample |
| 59 | +The following sample listens to the channel "channel" at a localhost Redis instance at "127.0.0.1:6379" |
23 | 60 | ```c#
|
24 |
| -namespace Microsoft.Azure.WebJobs.Extensions.Redis |
| 61 | +[FunctionName(nameof(PubSubTrigger))] |
| 62 | +public static void PubSubTrigger( |
| 63 | + [RedisPubSubTrigger(ConnectionString = "127.0.0.1:6379", Channel = "channel")] RedisMessageModel model, |
| 64 | + ILogger logger) |
25 | 65 | {
|
26 |
| - public class RedisMessageModel |
27 |
| - { |
28 |
| - public RedisTriggerType TriggerType { get; set; } |
29 |
| - public string Trigger { get; set; } |
30 |
| - public string Message { get; set; } |
31 |
| - } |
| 66 | + logger.LogInformation(JsonSerializer.Serialize(model)); |
32 | 67 | }
|
33 | 68 | ```
|
34 |
| -- `TriggerType`: The `RedisTriggerType` that the function uses |
35 |
| -- `Trigger`: The pubsub channel, key, or keyevent on which the function was triggered |
36 |
| -- `Message`: |
37 |
| - - If `TriggerType` is `PubSub`, this will be the message received by the pubsub channel |
38 |
| - - If `TriggerType` is `KeySpace`, this will be the keyevent that occurred on the key |
39 |
| - - If `TriggerType` is `KeyEvent`, this will be the key on which the keyevent occurred |
40 | 69 |
|
41 |
| -> **Note** |
42 |
| -> |
43 |
| -> If the input `Trigger` value is a glob pattern, the output `Trigger` value will be the exact pubsub channel, key, or keyevent, not the input `Trigger` value. |
44 |
| -> |
45 |
| -> For example, if the inputs to the function are `TriggerType=PubSub, Trigger="test*"`, and a message is published to the channel `"test2"`, the `Trigger` in the `RedisCacheMessageModel` will be `"test2"`. |
| 70 | +### `RedisListsTrigger` |
| 71 | +The `RedisListsTrigger` pops elements from a list and surfaces those elements to the function. The trigger polls Redis at a configurable fixed interval, and uses [`LPOP`](https://redis.io/commands/lpop/)/[`RPOP`](https://redis.io/commands/rpop/)/[`LMPOP`](https://redis.io/commands/lmpop/) to pop elements from the lists. |
46 | 72 |
|
47 |
| -### Example Function |
48 |
| -The following example shows a [C# function](https://learn.microsoft.com/azure/azure-functions/functions-dotnet-class-library) that gets invoked (by virtue of the trigger binding) when a message is published to a Redis channel queue named `channel`. |
| 73 | +Inputs: |
| 74 | +- `ConnectionString`: connection string to the redis cache (eg `<cacheName>.redis.cache.windows.net:6380,password=...`). |
| 75 | +- `Keys`: Keys to read from, space-delimited. |
| 76 | + - Multiple keys only supported on Redis 7.0+ using [`LMPOP`](https://redis.io/commands/lmpop/). |
| 77 | + - Listens to only the first key given in the argument using [`LPOP`](https://redis.io/commands/lpop/)/[`RPOP`](https://redis.io/commands/rpop/) on Redis versions less than 7.0. |
| 78 | +- (optional) `PollingIntervalInMs`: How often to poll Redis in milliseconds. |
| 79 | + - Default: 1000 |
| 80 | +- (optional) `MessagesPerWorker`: How many messages each functions worker "should" process. Used to determine how many workers the function should scale to. |
| 81 | + - Default: 100 |
| 82 | +- (optional) `BatchSize`: Number of elements to pull from Redis at one time. |
| 83 | + - Default: 10 |
| 84 | + - Only supported on Redis 6.2+ using the `COUNT` argument in [`LPOP`](https://redis.io/commands/lpop/)/[`RPOP`](https://redis.io/commands/rpop/). |
| 85 | +- (optional) `ListPopFromBeginning`: determines whether to pop elements from the beginning using [`LPOP`](https://redis.io/commands/lpop/) or to pop elements from the end using [`RPOP`](https://redis.io/commands/rpop/). |
| 86 | + - Default: true |
49 | 87 |
|
| 88 | +#### Sample |
| 89 | +The following sample polls the key "listTest" at a localhost Redis instance at "127.0.0.1:6379" |
50 | 90 | ```c#
|
51 |
| -[FunctionName("PubSubTrigger")] |
52 |
| -public static void PubSubTrigger( |
53 |
| - [RedisTrigger(ConnectionString = "<cacheName>.redis.cache.windows.net:6380", TriggerType = RedisTriggerType.PubSub, Trigger = "channel")] |
54 |
| - RedisMessageModel result, ILogger logger) |
| 91 | +[FunctionName(nameof(ListsTrigger))] |
| 92 | +public static void ListsTrigger( |
| 93 | + [RedisListsTrigger(ConnectionString = "127.0.0.1:6379", Keys = "listTest")] RedisMessageModel model, |
| 94 | + ILogger logger) |
55 | 95 | {
|
56 |
| - logger.LogInformation(JsonSerializer.Serialize(result)); |
| 96 | + logger.LogInformation(JsonSerializer.Serialize(model)); |
57 | 97 | }
|
58 | 98 | ```
|
59 | 99 |
|
60 |
| -## Getting Started |
61 |
| -First, [create a Redis cache](https://learn.microsoft.com/azure/azure-cache-for-redis/quickstart-create-redis). |
| 100 | +### `RedisStreamsTrigger` |
| 101 | +The `RedisStreamsTrigger` pops elements from a stream and surfaces those elements to the function. |
| 102 | +The trigger polls Redis at a configurable fixed interval, and uses [`XREADGROUP`](https://redis.io/commands/xreadgroup/) to read elements from the stream. |
| 103 | +Each function creates a new random GUID to use as its consumer name within the group to ensure that scaled out instances of the function will not read the same messages from the stream. |
| 104 | + |
| 105 | +Inputs: |
| 106 | +- `ConnectionString`: connection string to the redis cache (eg `<cacheName>.redis.cache.windows.net:6380,password=...`). |
| 107 | +- `Keys`: Keys to read from, space-delimited. |
| 108 | + - Uses [`XREADGROUP`](https://redis.io/commands/xreadgroup/). |
| 109 | +- (optional) `PollingIntervalInMs`: How often to poll Redis in milliseconds. |
| 110 | + - Default: 1000 |
| 111 | +- (optional) `MessagesPerWorker`: How many messages each functions worker "should" process. Used to determine how many workers the function should scale to. |
| 112 | + - Default: 100 |
| 113 | +- (optional) `BatchSize`: Number of elements to pull from Redis at one time. |
| 114 | + - Default: 10 |
| 115 | +- (optional) `ConsumerGroup`: The name of the consumer group that the function will use. |
| 116 | + - Default: "AzureFunctionRedisExtension" |
| 117 | +- (optional) `DeleteAfterProcess`: If the listener will delete the stream entries after the function runs. |
| 118 | + - Default: false |
| 119 | + |
| 120 | +#### Sample |
| 121 | +The following sample polls the key "streamTest" at a localhost Redis instance at "127.0.0.1:6379" |
| 122 | +```c# |
| 123 | +[FunctionName(nameof(StreamsTrigger))] |
| 124 | +public static void StreamsTrigger( |
| 125 | + [RedisStreamsTrigger(ConnectionString = "127.0.0.1:6379", Keys = "streamTest")] RedisMessageModel model, |
| 126 | + ILogger logger) |
| 127 | +{ |
| 128 | + logger.LogInformation(JsonSerializer.Serialize(model)); |
| 129 | +} |
| 130 | +``` |
| 131 | + |
| 132 | +### Return Value |
| 133 | +All triggers return a [`RedisMessageModel`](./src/Models/RedisMessageModel.cs) object that has two fields: |
| 134 | +```c# |
| 135 | +namespace Microsoft.Azure.WebJobs.Extensions.Redis |
| 136 | +{ |
| 137 | + public class RedisMessageModel |
| 138 | + { |
| 139 | + public string Trigger { get; set; } |
| 140 | + public string Message { get; set; } |
| 141 | + } |
| 142 | +} |
| 143 | +``` |
| 144 | +- `Trigger`: The pubsub channel, list key, or stream key that the function is listening to. |
| 145 | +- `Message`: The pubsub message, list element, or stream element. |
| 146 | + |
| 147 | +## Known Issues |
| 148 | +- The `RedisPubSubTrigger` is not capable of listening to [keyspace notifications](https://redis.io/docs/manual/keyspace-notifications/) on clustered caches. |
| 149 | + |
62 | 150 |
|
63 |
| -# Contributing |
64 |
| -This project welcomes contributions and suggestions. Most contributions require you to agree to a |
| 151 | +## Contributing |
| 152 | +This project welcomes contributions and suggestions. Most contributions require you to agree to a |
65 | 153 | Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us
|
66 | 154 | the rights to use your contribution. For details, visit https://cla.opensource.microsoft.com.
|
67 | 155 |
|
|
0 commit comments