notification

package module
v0.0.0-...-7e5e0b2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 12, 2026 License: Apache-2.0 Imports: 4 Imported by: 0

README

notifications

github.com/OpenNSW/core/notifications is its own Go module. It moved from github.com/OpenNSW/core/notification in the root module. The package is still named notification, so only the import path changes; code keeps using notification.X. Import it with the name written out, as goimports writes it when a package's name differs from its path:

import notification "github.com/OpenNSW/core/notifications"

A multi-channel notification router with a pluggable provider model. Your application registers one provider per channel type (email, SMS, etc.); the manager dispatches each Request to the correct provider at runtime.

Usage

Each provider takes its own typed config in its constructor and is handed, ready to send, to NewManager:

import (
    notification "github.com/OpenNSW/core/notifications"
    "github.com/OpenNSW/core/notifications/providers"
)

sms, err := providers.NewSMSProvider(cfg.Notification.SMS)
email, err := providers.NewEmailProvider(cfg.Notification.Email)

manager, err := notification.NewManager(sms, email)

err = manager.Send(ctx, notification.Request{
    Channel:  notification.ChannelEmail,
    To:       "applicant@example.com",
    Subject:  "Application received",
    Body:     "Your application #12345 has been received and is under review.",
    HTMLBody: "<p>Your application <strong>#12345</strong> has been received.</p>",
})

NewManager returns an error when it gets no providers, a nil one, or two for the same channel.

Channels

Constant Value
notification.ChannelEmail "email"
notification.ChannelSMS "sms"

Writing a provider

Implement notification.Provider:

type Provider interface {
    Type() ChannelType
    Send(ctx context.Context, req Request) error
}
  • Type() declares which channel this provider handles.
  • Send delivers the message.

Give the provider its own exported config type, with yaml tags, and a constructor that validates it and returns a ready provider, as providers.NewSMSProvider and providers.NewEmailProvider do:

type MyEmailConfig struct {
    APIKey string `yaml:"apiKey"`
}

func NewMyEmailProvider(cfg MyEmailConfig) (*MyEmailProvider, error) {
    if cfg.APIKey == "" {
        return nil, errors.New("apiKey is required")
    }
    return &MyEmailProvider{apiKey: cfg.APIKey}, nil
}

Provider configuration

An application embeds the provider configs in its own config struct and loads it with configyaml.LoadAndExpand, so a provider's credentials can come from an env var or a mounted file instead of the checked-in config:

type AppConfig struct {
    Notification struct {
        SMS   providers.SMSConfig   `yaml:"sms"`
        Email providers.EmailConfig `yaml:"email"`
    } `yaml:"notification"`
}
notification:
  sms:
    baseURL: https://sms.example.com
    userName: nsw
    password: "{{env:SMS_PASSWORD}}"
    sidCode: NSW
  email:
    baseURL: https://email.example.com
    token: "{{env:EMAIL_TOKEN}}"

The config fields are typed, so a value decodes into its field's type: a secret that only looks like a number (a password of 12345678, a SID code of 0123) stays the string it was. The email token is the bearer token itself; configyaml resolves the placeholder, and the provider uses it as written.

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrInvalidChannel = errors.New("invalid or missing channel")
	ErrToRequired     = errors.New("to address is required")
	ErrBodyRequired   = errors.New("body or html_body is required")
)
View Source
var ErrNoProviders = errors.New("notification: at least one provider is required")

ErrNoProviders is returned by NewManager when it is given no providers.

Functions

This section is empty.

Types

type ChannelType

type ChannelType string

ChannelType identifies the delivery channel for a notification.

const (
	ChannelSMS   ChannelType = "sms"
	ChannelEmail ChannelType = "email"
)

type Manager

type Manager struct {
	// contains filtered or unexported fields
}

Manager routes notification requests to registered providers. It is safe for concurrent use after construction.

func NewManager

func NewManager(providers ...Provider) (*Manager, error)

NewManager returns a Manager that routes each request to the provider for its channel. The providers are already configured by their constructors. Returns an error if none is given, one is nil, or two handle the same channel.

func (*Manager) Send

func (m *Manager) Send(ctx context.Context, req Request) error

Send validates req and dispatches it to the registered provider for req.Channel. Returns an error if the request is invalid, no provider is registered for the channel, or the provider's Send call fails.

type Provider

type Provider interface {
	Type() ChannelType
	Send(ctx context.Context, req Request) error
}

Provider is implemented by each notification channel (email, SMS, etc.). A provider is built ready to send, from its own config type, by its constructor (e.g. providers.NewSMSProvider), and handed to NewManager.

type Request

type Request struct {
	Channel  ChannelType `json:"channel"`
	To       string      `json:"to"`
	Subject  string      `json:"subject,omitempty"`
	Body     string      `json:"body,omitempty"`
	HTMLBody string      `json:"html_body,omitempty"`
}

func (Request) Validate

func (r Request) Validate() error

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL