Overview
The Notifications Service handles creation and delivery of user notifications.
Service Details:
- Package:
notifications
- Port:
50054
- Proto:
proto/notifications/notifications.proto
Service Definition
service NotificationsService {
rpc CreateNotification(CreateNotificationRequest) returns (CreateNotificationResponse) {}
rpc MarkNotificationsRead(MarkNotificationsReadRequest) returns (MarkNotificationsReadResponse) {}
rpc ListNotifications(ListNotificationsRequest) returns (ListNotificationsResponse) {}
}
RPC Methods
CreateNotification
Internal API - Not exposed to public. Used by other services to create notifications.
Create a new notification for a user.
Request:
Type of notification (e.g., “workflow_failed”, “job_completed”, “threshold_reached”)
JSON string containing notification data
Response:
Unique identifier of the created notification
Example:
req := ¬ifications.CreateNotificationRequest{
UserId: "user-123",
Kind: "workflow_failed",
Payload: `{
"workflow_id": "workflow-456",
"workflow_name": "API Monitor",
"failure_count": 3
}`,
}
resp, err := client.CreateNotification(ctx, req)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Notification created: %s\n", resp.Id)
# Using grpcurl (internal service)
grpcurl -plaintext -d '{
"user_id": "user-123",
"kind": "workflow_failed",
"payload": "{\"workflow_id\": \"workflow-456\"}"
}' localhost:50054 notifications.NotificationsService/CreateNotification
MarkNotificationsRead
Mark one or more notifications as read.
Request:
Array of notification IDs to mark as read
User ID (for authorization)
Response:
Empty response on success.
Example:
req := ¬ifications.MarkNotificationsReadRequest{
Ids: []string{"notif-001", "notif-002", "notif-003"},
UserId: "user-123",
}
_, err := client.MarkNotificationsRead(ctx, req)
if err != nil {
log.Fatal(err)
}
fmt.Println("Notifications marked as read")
# Using grpcurl
grpcurl -plaintext -d '{
"ids": ["notif-001", "notif-002"],
"user_id": "user-123"
}' localhost:50054 notifications.NotificationsService/MarkNotificationsRead
ListNotifications
Retrieve a paginated list of notifications for a user.
Request:
Pagination cursor (empty for first page)
Response:
Array of notification objects
Cursor for next page (empty if no more pages)
NotificationResponse:
Timestamp when marked as read (empty if unread)
Example:
req := ¬ifications.ListNotificationsRequest{
UserId: "user-123",
Cursor: "",
}
resp, err := client.ListNotifications(ctx, req)
if err != nil {
log.Fatal(err)
}
for _, notif := range resp.Notifications {
status := "unread"
if notif.ReadAt != "" {
status = "read"
}
fmt.Printf("[%s] %s: %s\n", status, notif.Kind, notif.Payload)
}
// Fetch next page if available
if resp.Cursor != "" {
nextReq := ¬ifications.ListNotificationsRequest{
UserId: "user-123",
Cursor: resp.Cursor,
}
// ... fetch next page
}
# Using grpcurl
grpcurl -plaintext -d '{
"user_id": "user-123",
"cursor": ""
}' localhost:50054 notifications.NotificationsService/ListNotifications
Notification Types
Common notification kinds used in Chronoverse:
| Kind | Description | Payload Example |
|---|
workflow_failed | Workflow reached failure threshold | {"workflow_id": "...", "failure_count": 3} |
workflow_terminated | Workflow was terminated | {"workflow_id": "...", "reason": "max_failures"} |
job_completed | Job execution completed | {"job_id": "...", "status": "success"} |
job_failed | Job execution failed | {"job_id": "...", "error": "..."} |
threshold_warning | Approaching failure threshold | {"workflow_id": "...", "current": 2, "max": 3} |
Connection Example
package main
import (
"context"
"log"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
pb "github.com/hitesh22rana/chronoverse/pkg/proto/go/notifications"
)
func main() {
conn, err := grpc.Dial(
"localhost:50054",
grpc.WithTransportCredentials(insecure.NewCredentials()),
)
if err != nil {
log.Fatalf("Failed to connect: %v", err)
}
defer conn.Close()
client := pb.NewNotificationsServiceClient(conn)
ctx := context.Background()
// List notifications
resp, err := client.ListNotifications(ctx, &pb.ListNotificationsRequest{
UserId: "user-123",
Cursor: "",
})
if err != nil {
log.Fatalf("ListNotifications failed: %v", err)
}
unreadCount := 0
for _, notif := range resp.Notifications {
if notif.ReadAt == "" {
unreadCount++
}
}
log.Printf("Total: %d, Unread: %d", len(resp.Notifications), unreadCount)
}
Integration Example
Example of creating a notification when a workflow fails:
// In Workflows Service - after detecting failure threshold
if thresholdReached {
// Call Notifications Service
notifClient := notifications.NewNotificationsServiceClient(notifConn)
_, err := notifClient.CreateNotification(ctx, ¬ifications.CreateNotificationRequest{
UserId: workflow.UserId,
Kind: "workflow_failed",
Payload: fmt.Sprintf(`{
"workflow_id": "%s",
"workflow_name": "%s",
"failure_count": %d
}`, workflow.Id, workflow.Name, workflow.ConsecutiveJobFailuresCount),
})
if err != nil {
log.Printf("Failed to create notification: %v", err)
}
}