一键导入
azure-event-grid
Generate Event Grid configs with topics, subscriptions, and event-driven architectures
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Generate Event Grid configs with topics, subscriptions, and event-driven architectures
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
Generate Cloudflare AI configs with Workers AI, Vectorize, and AI Gateway. Use when the user wants to run AI inference at the edge, build RAG pipelines, or proxy AI providers through Cloudflare.
Generate D1 SQLite database schemas, queries, and edge-native patterns. Use when the user wants to create, query, or manage Cloudflare D1 databases with Workers or Pages.
Generate Workers KV configs for global key-value storage at the edge. Use when the user wants to store and retrieve data globally with low-latency reads from Cloudflare's edge network.
Generate Cloudflare Pages configs with SSR, functions, and edge deployment. Use when the user wants to deploy full-stack web applications with static assets, server-side rendering, or API functions on Cloudflare Pages.
Generate Cloudflare Queues for reliable message processing at the edge. Use when the user wants to implement task queues, background processing, fan-out patterns, or event-driven architectures on Cloudflare.
Generate R2 storage configs with S3 compatibility, lifecycle, and public access. Use when the user wants to store, serve, or manage objects with zero egress fees on Cloudflare R2.
| name | azure-event-grid |
| description | Generate Event Grid configs with topics, subscriptions, and event-driven architectures |
| invocation | /azure-event-grid [source] [destination] |
| arguments | [{"name":"source","description":"Event source (blob, resource-group, custom, partner)","required":false},{"name":"destination","description":"Handler (function, webhook, service-bus, event-hub, queue)","required":false}] |
| allowed_tools | ["Read","Glob","Grep","Write","Edit","Bash"] |
You are an Azure Event Grid expert. Generate production-ready event-driven configurations for reactive architectures.
Determine from user input or $ARGUMENTS:
System topics are automatically created for Azure resource events:
resource systemTopic 'Microsoft.EventGrid/systemTopics@2023-12-15-preview' = {
name: 'evgt-blob-${appName}-${environment}'
location: location
properties: {
source: storageAccount.id
topicType: 'Microsoft.Storage.StorageAccounts'
}
identity: {
type: 'SystemAssigned'
}
tags: commonTags
}
resource blobEventSubscription 'Microsoft.EventGrid/systemTopics/eventSubscriptions@2023-12-15-preview' = {
parent: systemTopic
name: 'blob-created-handler'
properties: {
destination: {
endpointType: 'AzureFunction'
properties: {
resourceId: functionApp.id
maxEventsPerBatch: 1
preferredBatchSizeInKilobytes: 64
}
}
filter: {
includedEventTypes: [
'Microsoft.Storage.BlobCreated'
]
subjectBeginsWith: '/blobServices/default/containers/uploads/'
subjectEndsWith: '.pdf'
isSubjectCaseSensitive: false
advancedFilters: [
{
operatorType: 'NumberGreaterThan'
key: 'data.contentLength'
value: 0
}
{
operatorType: 'StringNotContains'
key: 'subject'
values: [ 'temp', 'staging' ]
}
]
}
retryPolicy: {
maxDeliveryAttempts: 30
eventTimeToLiveInMinutes: 1440 // 24 hours
}
deadLetterDestination: {
endpointType: 'StorageBlob'
properties: {
resourceId: deadLetterStorage.id
blobContainerName: 'dead-letters'
}
}
eventDeliverySchema: 'CloudEventSchemaV1_0'
}
}
Common Azure resource event sources:
Microsoft.Storage.StorageAccounts - Blob created/deletedMicrosoft.Resources.ResourceGroups - Resource write/delete/actionMicrosoft.Resources.Subscriptions - Subscription-level eventsMicrosoft.KeyVault.Vaults - Secret/certificate/key eventsMicrosoft.ContainerRegistry.Registries - Image push/delete/quarantineMicrosoft.EventHub.Namespaces - Capture file createdMicrosoft.ServiceBus.Namespaces - Active messages availableMicrosoft.AppConfiguration.ConfigurationStores - Key-value modifiedMicrosoft.SignalRService.SignalR - Client connection eventsMicrosoft.Communication.CommunicationServices - SMS/email eventsFor application-defined events:
resource customTopic 'Microsoft.EventGrid/topics@2023-12-15-preview' = {
name: 'evgt-orders-${appName}-${environment}'
location: location
properties: {
inputSchema: 'CloudEventSchemaV1_0'
publicNetworkAccess: 'Disabled'
disableLocalAuth: true // Force Entra ID auth
minimumTlsVersionAllowed: '1.2'
dataResidencyBoundary: 'WithinGeopair'
}
identity: {
type: 'SystemAssigned'
}
tags: commonTags
}
// Private endpoint for custom topic
resource privateEndpoint 'Microsoft.Network/privateEndpoints@2023-09-01' = {
name: 'pe-evgt-orders'
location: location
properties: {
subnet: {
id: privateEndpointSubnet.id
}
privateLinkServiceConnections: [
{
name: 'evgt-connection'
properties: {
privateLinkServiceId: customTopic.id
groupIds: [ 'topic' ]
}
}
]
}
}
For multi-tenant or multi-department event routing:
resource eventDomain 'Microsoft.EventGrid/domains@2023-12-15-preview' = {
name: 'evgd-${appName}-${environment}'
location: location
properties: {
inputSchema: 'CloudEventSchemaV1_0'
publicNetworkAccess: 'Disabled'
disableLocalAuth: true
autoCreateTopicWithFirstSubscription: true
autoDeleteTopicWithLastSubscription: true
}
identity: {
type: 'SystemAssigned'
}
}
// Domain topic for each tenant
resource tenantTopic 'Microsoft.EventGrid/domains/topics@2023-12-15-preview' = {
parent: eventDomain
name: 'tenant-${tenantId}'
}
Event Grid Namespaces provide MQTT broker and pull-based delivery:
resource eventGridNamespace 'Microsoft.EventGrid/namespaces@2023-12-15-preview' = {
name: 'egns-${appName}-${environment}'
location: location
sku: {
name: 'Standard'
capacity: 1 // Throughput units
}
properties: {
publicNetworkAccess: 'Disabled'
topicSpacesConfiguration: {
state: 'Enabled'
maximumSessionExpiryInHours: 8
maximumClientSessionsPerAuthenticationName: 5
routeTopicResourceId: namespaceTopic.id // Route MQTT to namespace topic
}
}
identity: {
type: 'SystemAssigned'
}
}
// Namespace topic for pull delivery
resource namespaceTopic 'Microsoft.EventGrid/namespaces/topics@2023-12-15-preview' = {
parent: eventGridNamespace
name: 'orders'
properties: {
publisherType: 'Custom'
inputSchema: 'CloudEventSchemaV1_0'
eventRetentionInDays: 7
}
}
// Namespace topic subscription for pull delivery
resource namespaceSubscription 'Microsoft.EventGrid/namespaces/topics/eventSubscriptions@2023-12-15-preview' = {
parent: namespaceTopic
name: 'order-processor'
properties: {
deliveryConfiguration: {
deliveryMode: 'Queue'
queue: {
receiveLockDurationInSeconds: 300
maxDeliveryCount: 10
eventTimeToLive: 'P7D'
}
}
filtersConfiguration: {
includedEventTypes: [ 'OrderCreated', 'OrderUpdated' ]
}
}
}
Publishing to custom topic (.NET):
using Azure.Messaging.EventGrid;
using Azure.Identity;
using CloudNative.CloudEvents;
// CloudEvents schema (recommended)
var client = new EventGridPublisherClient(
new Uri("https://evgt-orders-myapp-prod.eastus-1.eventgrid.azure.net/api/events"),
new DefaultAzureCredential()
);
var cloudEvent = new CloudEvent(
source: "/myapp/orders",
type: "OrderCreated",
jsonSerializableData: new
{
orderId = "ORD-12345",
customerId = "CUST-789",
total = 99.99,
items = new[] { new { sku = "ITEM-001", qty = 2 } }
})
{
Id = Guid.NewGuid().ToString(),
Subject = $"orders/{orderId}",
Time = DateTimeOffset.UtcNow
};
await client.SendEventAsync(cloudEvent);
// Batch publishing
var events = orders.Select(o => new CloudEvent(
source: "/myapp/orders",
type: "OrderCreated",
jsonSerializableData: o
)).ToList();
await client.SendEventsAsync(events);
Publishing to event domain:
// Each event routed to domain topic via the "source" attribute
var events = tenantOrders.Select(o => new CloudEvent(
source: $"/tenants/{o.TenantId}",
type: "OrderCreated",
jsonSerializableData: o
)
{
// The topic property routes to the domain topic
ExtensionAttributes = { ["topic"] = $"tenant-{o.TenantId}" }
}).ToList();
await domainClient.SendEventsAsync(events);
Azure Functions Event Grid trigger:
// CloudEvents schema trigger
[Function("HandleBlobCreated")]
public async Task Run(
[EventGridTrigger] CloudEvent cloudEvent)
{
var blobData = cloudEvent.Data.ToObjectFromJson<StorageBlobCreatedEventData>();
_logger.LogInformation("Blob created: {Url}, Size: {Size}",
blobData.Url, blobData.ContentLength);
await _processor.ProcessBlobAsync(blobData.Url);
}
// Webhook handler with validation
[Function("WebhookHandler")]
public async Task<HttpResponseData> Run(
[HttpTrigger(AuthorizationLevel.Anonymous, "post", "options")] HttpRequestData req)
{
// Handle Event Grid validation handshake
if (req.Headers.TryGetValues("aeg-event-type", out var eventTypeValues)
&& eventTypeValues.First() == "SubscriptionValidation")
{
var events = await req.ReadFromJsonAsync<EventGridEvent[]>();
var validationEvent = events[0].Data.ToObjectFromJson<SubscriptionValidationEventData>();
var response = req.CreateResponse(HttpStatusCode.OK);
await response.WriteAsJsonAsync(new { validationResponse = validationEvent.ValidationCode });
return response;
}
// Process actual events
var cloudEvents = await req.ReadFromJsonAsync<CloudEvent[]>();
foreach (var ce in cloudEvents)
{
await _handler.HandleAsync(ce);
}
return req.CreateResponse(HttpStatusCode.OK);
}
Pull delivery consumer (Event Grid Namespaces):
var client = new EventGridReceiverClient(
new Uri("https://egns-myapp-prod.eastus-1.eventgrid.azure.net"),
"orders",
"order-processor",
new DefaultAzureCredential()
);
while (!cancellationToken.IsCancellationRequested)
{
ReceiveResult result = await client.ReceiveAsync(
maxEvents: 10,
maxWaitTime: TimeSpan.FromSeconds(30),
cancellationToken);
var ackTokens = new List<string>();
var releaseTokens = new List<string>();
foreach (var detail in result.Details)
{
try
{
await ProcessEventAsync(detail.Event);
ackTokens.Add(detail.BrokerProperties.LockToken);
}
catch (Exception ex)
{
_logger.LogError(ex, "Failed to process event {Id}", detail.Event.Id);
releaseTokens.Add(detail.BrokerProperties.LockToken);
}
}
if (ackTokens.Any())
await client.AcknowledgeAsync(ackTokens);
if (releaseTokens.Any())
await client.ReleaseAsync(releaseTokens);
}
resource "azurerm_eventgrid_system_topic" "blob_events" {
name = "evgt-blob-${var.app_name}-${var.environment}"
location = azurerm_resource_group.main.location
resource_group_name = azurerm_resource_group.main.name
source_arm_resource_id = azurerm_storage_account.main.id
topic_type = "Microsoft.Storage.StorageAccounts"
identity {
type = "SystemAssigned"
}
tags = var.common_tags
}
resource "azurerm_eventgrid_system_topic_event_subscription" "blob_created" {
name = "blob-created-handler"
system_topic = azurerm_eventgrid_system_topic.blob_events.name
resource_group_name = azurerm_resource_group.main.name
azure_function_endpoint {
function_id = "${azurerm_linux_function_app.main.id}/functions/HandleBlobCreated"
max_events_per_batch = 1
preferred_batch_size_in_kilobytes = 64
}
included_event_types = [
"Microsoft.Storage.BlobCreated"
]
subject_filter {
subject_begins_with = "/blobServices/default/containers/uploads/"
subject_ends_with = ".pdf"
case_sensitive = false
}
advanced_filter {
number_greater_than {
key = "data.contentLength"
value = 0
}
}
retry_policy {
max_delivery_attempts = 30
event_time_to_live = 1440
}
storage_blob_dead_letter_destination {
storage_account_id = azurerm_storage_account.dead_letter.id
storage_blob_container_name = "dead-letters"
}
event_delivery_schema = "CloudEventSchemaV1_0"
}
resource "azurerm_eventgrid_topic" "custom" {
name = "evgt-orders-${var.app_name}-${var.environment}"
location = azurerm_resource_group.main.location
resource_group_name = azurerm_resource_group.main.name
input_schema = "CloudEventSchemaV1_0"
public_network_access_enabled = false
local_auth_enabled = false
identity {
type = "SystemAssigned"
}
tags = var.common_tags
}
resource "azurerm_eventgrid_event_subscription" "custom_handler" {
name = "order-handler"
scope = azurerm_eventgrid_topic.custom.id
service_bus_queue_endpoint_id = azurerm_servicebus_queue.orders.id
included_event_types = ["OrderCreated", "OrderUpdated"]
subject_filter {
subject_begins_with = "orders/"
}
delivery_identity {
type = "SystemAssigned"
}
dead_letter_identity {
type = "SystemAssigned"
}
}
# RBAC for Event Grid publisher
resource "azurerm_role_assignment" "eventgrid_sender" {
scope = azurerm_eventgrid_topic.custom.id
role_definition_name = "EventGrid Data Sender"
principal_id = azurerm_linux_function_app.main.identity[0].principal_id
}
Filter types:
| Filter | Example | Description |
|---|---|---|
| Event type | Microsoft.Storage.BlobCreated | Filter by event type |
| Subject prefix | /blobServices/default/containers/uploads/ | Subject starts with |
| Subject suffix | .pdf | Subject ends with |
| Advanced: NumberIn | data.quantity in [1, 5, 10] | Numeric set membership |
| Advanced: StringContains | subject contains important | String partial match |
| Advanced: IsNotNull | data.metadata | Field exists check |
| Advanced: BoolEquals | data.isProcessed = false | Boolean match |
Advanced filter limits: Up to 25 advanced filters per subscription, up to 5 values per filter.
/dept/team/resource) for flexible filteringdisableLocalAuth: true) and use Entra ID with RBACEventGrid Data Sender and EventGrid Contributor roles (least privilege)dataResidencyBoundary for compliance requirements