Skip to content

Azure Event Grid

Publish OData entity change events to an Azure Event Grid topic using the ext/azure extension.

Installation

go get github.com/jhonsferg/traverse/ext/azure

Quick Start

import "github.com/jhonsferg/traverse/ext/azure"

client := azure.NewEventGridClient(
    "https://mytopic.westus2-1.eventgrid.azure.net/api/events",
    "your-sas-key",
    "traverse/myapp",
)

pub := azure.NewChangePublisher(client, "Customers")

// After a successful POST:
if err := pub.AfterCreate(ctx, "42", newCustomer); err != nil {
    log.Printf("event publish failed: %v", err)
}

// After a successful PATCH/PUT:
if err := pub.AfterUpdate(ctx, "42", oldCustomer, newCustomer); err != nil {
    log.Printf("event publish failed: %v", err)
}

// After a successful DELETE:
if err := pub.AfterDelete(ctx, "42", oldCustomer); err != nil {
    log.Printf("event publish failed: %v", err)
}

API Reference

EventGridClient

Low-level client that posts events directly to an Event Grid topic endpoint.

type EventGridClient struct { /* unexported */ }

func NewEventGridClient(topicEndpoint, topicKey, source string) *EventGridClient
  • topicEndpoint – full topic URL, e.g. https://mytopic.westus2-1.eventgrid.azure.net/api/events
  • topicKey – access key from the Azure Portal
  • source – event source identifier, e.g. "traverse/myapp"

Publish

func (c *EventGridClient) Publish(ctx context.Context, events []EventGridEvent) error

Sends a batch of events as a JSON array (up to 1 MB per batch).

PublishEntityChange

func (c *EventGridClient) PublishEntityChange(
    ctx context.Context,
    entitySet, entityID, changeType string,
    oldValue, newValue interface{},
) error

Convenience wrapper that constructs an EventGridEvent with an ODataChangeData payload and publishes it. changeType should be "created", "updated", or "deleted".

ChangePublisher

Higher-level helper scoped to a single entity set.

type ChangePublisher struct { /* unexported */ }

func NewChangePublisher(client *EventGridClient, entitySet string) *ChangePublisher

func (p *ChangePublisher) AfterCreate(ctx context.Context, entityID string, newValue interface{}) error
func (p *ChangePublisher) AfterUpdate(ctx context.Context, entityID string, oldValue, newValue interface{}) error
func (p *ChangePublisher) AfterDelete(ctx context.Context, entityID string, oldValue interface{}) error

Event types

Event types are generated by EventTypeFor:

changeType eventType
"created" traverse.entity.created
"updated" traverse.entity.updated
"deleted" traverse.entity.deleted

ODataChangeData

Payload carried in EventGridEvent.Data:

type ODataChangeData struct {
    EntitySet  string      `json:"entitySet"`
    EntityID   string      `json:"entityId"`
    ChangeType string      `json:"changeType"` // "created" | "updated" | "deleted"
    OldValue   interface{} `json:"oldValue,omitempty"`
    NewValue   interface{} `json:"newValue,omitempty"`
}

Notes / Limitations

  • Authentication uses SAS key via the aeg-sas-key header. Managed Identity and shared-access-signature token auth are not built in.
  • The extension uses the Event Grid schema v1, not CloudEvents schema.
  • Batch size is not automatically split; callers must keep payloads under 1 MB.
  • Events are fire-and-forget relative to the OData operation - a publish failure does not roll back the entity change.