Skip to content

Solsynth/DysonNoti

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

28 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

DysonRing

Go implementation of the Dyson Network Ring notification service. Handles push notifications, email delivery, and Server-Sent Events (SSE) streaming for real-time notifications.

Features

  • Push Notifications: APNs (Apple), FCM (Google), UnifiedPush, and WebSocket relay
  • Email Delivery: SMTP-based email sender
  • SOP Streaming: Server-Sent Events plus a polling list for recent notifications
  • gRPC API: High-performance notification delivery API
  • HTTP API: REST endpoints for notifications, subscriptions, and preferences
  • Background Jobs: In-process worker pool with graceful shutdown
  • Retention: Configurable notification and soft-delete cleanup

Quick Start

Prerequisites

  • Go 1.22+
  • PostgreSQL 14+
  • (Optional) Redis for session/queue caching

Configuration

Copy and edit the example config:

cp config.example.toml config.toml

Key settings:

[http]
host = "0.0.0.0"
port = 8080

[grpc]
host = "0.0.0.0"
port = 9090
useTLS = false
certFile = ""
keyFile = ""

[database]
dsn = "postgres://postgres:postgres@localhost:5432/dyson_ring?sslmode=disable"

Build & Run

go build -o dyson-ring ./cmd
./dyson-ring serve -config config.toml

Database Migration

Import legacy data from another Postgres database into the current schema:

./dyson-ring migrate \
  -config config.toml \
  -source-dsn "postgres://old-user:old-pass@localhost:5432/old_db?sslmode=disable"

-source-dsn also accepts PostgreSQL keyword/value DSNs like host=... port=... dbname=... user=... password=..., but quote the whole value so your shell passes it as one argument.

Useful flags:

./dyson-ring migrate -source-dsn "..." -batch-size 500
./dyson-ring migrate -source-dsn "..." -provider-map "0:apple,1:google,2:unifiedpush,3:sop,4:websocket"
./dyson-ring migrate -source-dsn "..." -priority-map "0:normal,1:normal,2:normal,3:normal,4:high,5:high,6:high,7:high,8:critical,9:critical,10:critical"
./dyson-ring migrate -source-dsn "..." -preference-map "0:normal,1:muted,2:nopush,3:noemail,4:rejected"

The migration runs incrementally by batch and checks the target row count before continuing, so reruns resume from the current imported count.

Project Structure

cmd/                    # CLI entrypoint
internal/
├── app/                # Runtime composition and lifecycle
├── config/             # Viper-backed configuration
├── db/                 # Migration helpers
├── dispatch/           # Worker pool and job processing
├── email/              # SMTP email sender
├── flush/              # Invalid token flush buffer
├── grpcsvc/            # gRPC Ring service implementation
├── handler/            # HTTP handlers
├── model/              # Domain models
├── preference/         # Preference service
├── push/               # Push delivery (providers, SOP, deliverer)
├── retention/          # Cleanup jobs
├── server/             # Gin router setup
└── store/              # PostgreSQL data access
migrations/              # SQL migrations
config.example.toml
go.mod

HTTP API

Notifications

Method Endpoint Description
GET /api/notifications/count Unread count
GET /api/notifications/ List notifications
POST /api/notifications/all/read Mark all as read
POST /api/notifications/send Send notification

Subscriptions

Method Endpoint Description
PUT /api/notifications/subscription Upsert subscription
GET /api/notifications/subscription List subscriptions
GET /api/notifications/subscription/current Get current device subscription
DELETE /api/notifications/subscription/:id Delete subscription

Preferences

Method Endpoint Description
GET /api/notifications/preferences List preferences
GET /api/notifications/preferences/:topic Get topic preference
PUT /api/notifications/preferences/:topic Upsert preference
DELETE /api/notifications/preferences/:topic Soft-delete preference

SOP Streaming

Method Endpoint Description
POST /api/notifications/sop/subscription Register SOP subscription
GET /api/notifications/sop/ List SOP subscriptions
GET /api/notifications/sop/poll List recent SOP notifications for polling clients
GET /api/notifications/sop/stream SSE stream (token via query/header)

Health

Method Endpoint Description
GET /health Liveness check
GET /ready Readiness check (DB ping)

gRPC API

Implements DyRingService:

  • SendEmail - Queue email delivery
  • SendPushNotificationToUser - Send to single user
  • SendPushNotificationToUsers - Fan out to multiple users
  • UnsubscribePushNotifications - Remove subscriptions by device ID

Configuration Reference

[app]
name = "dyson-ring"
env = "development"  # or "production"

[http]
host = "0.0.0.0"
port = 8080

[grpc]
host = "0.0.0.0"
port = 9090
useTLS = true
certFile = "/app/keys/server.crt"
keyFile = "/app/keys/server.key"

[database]
dsn = "postgres://..."
max_conns = 10

[redis]
addr = "localhost:6379"

[worker]
count = 0          # 0 = runtime.NumCPU()
buffer = 100

[email]
server = "smtp.example.com"
port = 587
use_ssl = false
from_address = "notifications@example.com"
from_name = "Dyson Notifications"
subject_prefix = "[Dyson]"

[apple]
private_key_path = "/path/to/apns.p8"
private_key_id = "KEYID"
team_id = "TEAMID"
bundle_id = "com.dyson.app"
production = false

[google]
service_account_path = "/path/to/firebase.json"

[flush]
interval = "30s"
max_size = 100

[retention]
notification_days = 90
soft_delete_days = 30

Push Provider Priority

  1. SOP (if active stream connected)
  2. Apple (APNs)
  3. Google (FCM)
  4. UnifiedPush

Device Grouping

  • Device IDs with :sop suffix are normalized for grouping
  • One effective push target per physical device
  • SOP preferred when connected

Testing

go test ./... -v

Development

# Tidy dependencies
go mod tidy

# Build
go build ./...

# Run tests
go test ./...

Docker

docker build -t dyson-ring .

Operational Notes

  • In-process queue means no cross-node job distribution
  • SOP stream map is process-local
  • Backpressure via channel blocking (not broker buffering)
  • For horizontal scale later: swap dispatcher channel for Redis Streams/JetStream

About

The Solar Network Push

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors