Skip to content

Event System

TheMinecraftGuyGuru edited this page Jun 8, 2026 · 6 revisions

Event System

Philosophy

Event-driven everything. Do NOT tightly couple modules.

MuxCore uses events as the primary integration pattern. Modules publish events when state changes; other modules subscribe to react.

Event Bus

MuxCore provides an in-memory event bus by default. NATS is available as an optional module (eventbus-nats) for distributed messaging.

Core defines only module-lifecycle and cluster-lifecycle event types. Domain event types (download.*, playback.*, transcode.*, etc.) are defined in their respective contract repos.

Event Structure

type Event struct {
    ID          string
    Type        string    // e.g., "download.completed" (defined in contracts-downloader)
    Source      string    // e.g., "module:downloader-qbittorrent"
    Payload     []byte    // JSON or protobuf
    Metadata    map[string]string
    Timestamp   time.Time
}

Fabric Events (in core)

Event Description
module.registered Module discovered and registered
module.unregistered Module removed
module.degraded Module running with reduced capabilities
cluster.node.joined Node joined the cluster
cluster.node.left Node left the cluster
cluster.leader.changed Cluster leader changed

Domain Events (in contract repos)

Domain event types and payloads are defined in their respective contract repos:

Contract Repo Example Events
contracts-media library.item.added, library.item.removed
contracts-downloader download.started, download.completed, download.failed
contracts-playback playback.started, playback.stopped, stream.*
contracts-transcoder transcode.started, transcode.completed, transcode.failed
contracts-metadata metadata.fetched
contracts-artwork artwork.fetched
contracts-content content.missing, content.fetched
contracts-discovery discovery.updated
contracts-quality quality.decision, format.matched
contracts-mediainfo media.analyzed

Publishing Events

import dl "github.com/Muxcore-Media/contracts-downloader"

payload, _ := json.Marshal(dl.DownloadCompletedPayload{
    DownloadID: id,
    Title:      title,
})

deps.EventBus.Publish(ctx, contracts.Event{
    Type:    dl.EventDownloadCompleted,
    Source:  "my-downloader",
    Payload: payload,
})

Subscribing to Events

import dl "github.com/Muxcore-Media/contracts-downloader"

deps.EventBus.Subscribe(ctx, dl.EventDownloadCompleted,
    func(ctx context.Context, event contracts.Event) error {
        var payload dl.DownloadCompletedPayload
        json.Unmarshal(event.Payload, &payload)
        return nil
    })

Event-Driven Workflow Example

User clicks "Request Movie"
  -> publishes media.requested (from contracts-media)

Workflow Engine receives media.requested
  -> starts "movie-request" workflow

Step 1: Metadata Lookup -> request/reply to metadata provider
Step 2: Indexer Search -> request/reply to indexer modules
Step 3: Download -> downloader publishes download.completed when done
Step 4: Import -> publishes library.item.added
Step 5: Notify -> notification module sends alert

Each step is an event. The workflow engine orchestrates but doesn't implement any step directly.

Anti-Patterns

Don't: Direct Module Calls

// BAD: Tight coupling
client := downloader.NewClient()
client.AddMagnet(magnet)

Do: Event-Driven

// GOOD: Loose coupling
bus.Publish(ctx, Event{
    Type: dl.EventDownloadApproved,
    Payload: payload,
})

Clone this wiki locally