# CasaOS Service Layer Architecture: How Services Communicate in the Repository Pattern

> Discover the CasaOS service layer architecture. Learn how services communicate using direct Go method calls and the CasaOS Message Bus for efficient operations.

- Repository: [IceWhale/CasaOS](https://github.com/IceWhaleTech/CasaOS)
- Tags: architecture
- Published: 2026-06-28

---

**CasaOS implements a repository-style service layer where a global singleton `service.MyService` exposes all domain services via the `Repository` interface, enabling direct Go method calls for synchronous operations and the CasaOS Message Bus for asynchronous event distribution.**

The CasaOS service layer architecture follows a clean, modular design that separates business logic from transport concerns. At its core lies a singleton repository pattern that aggregates all services—such as system management, notifications, and peer discovery—into a single access point. This architecture supports multiple communication pathways, from simple in-process method calls to distributed event broadcasting, making it straightforward for HTTP handlers and background jobs to interact with domain logic.

## Core Service Layer Design

### The Repository Interface

The foundation of the service layer resides in [`service/service.go`](https://github.com/IceWhaleTech/CasaOS/blob/main/service/service.go), which defines the `Repository` interface and constructs concrete service implementations. This interface acts as a service locator, exposing methods like `Casa()`, `Notify()`, `System()`, and `Gateway()` to retrieve specific service instances.

```go
type Repository interface {
    Casa() CasaService
    Notify() NotifyServer
    System() SystemService
    Gateway() external.ManagementService
    MessageBus() *codegen.ClientWithResponses
    // ... additional service accessors
}

func NewService(db *gorm.DB, RuntimePath string) Repository {
    return &store{
        casa:   NewCasaService(),
        notify: NewNotifyService(db),
        system: NewSystemService(),
        // ... other initializations
    }
}

```

The repository is instantiated once during application bootstrap in [`main/main.go`](https://github.com/IceWhaleTech/CasaOS/blob/main/main/main.go):

```go
service.MyService = service.NewService(sqliteDB, config.CommonInfo.RuntimePath)
service.Cache = cache.Init()

```

### Concrete Service Implementations

Each domain service lives in its own file under the `service/` directory and implements a thin interface:

- **[`service/system.go`](https://github.com/IceWhaleTech/CasaOS/blob/main/service/system.go)**: Implements `SystemService` for hardware introspection and system control (e.g., `GetCpuPercent()`, reboot/shutdown operations).
- **[`service/notify.go`](https://github.com/IceWhaleTech/CasaOS/blob/main/service/notify.go)**: Implements `NotifyServer` for managing notification logs and publishing events to the Message Bus via `SendNotify()`.
- **[`service/casa.go`](https://github.com/IceWhaleTech/CasaOS/blob/main/service/casa.go)**: Implements `CasaService` for remote version checking with built-in caching via `go-cache`.
- **[`service/connections.go`](https://github.com/IceWhaleTech/CasaOS/blob/main/service/connections.go)**: Implements `ConnectionsService` for DB-driven CIFS mount management.

## Service Communication Patterns

### Direct Method Calls via Singleton

The primary communication mechanism involves direct Go method calls through the global `service.MyService` variable. HTTP handlers and background tasks obtain service references and invoke methods synchronously:

```go
// Example from route/v1/system.go
need, version := version.IsNeedUpdate(service.MyService.Casa().GetCasaosVersion())
cpuPercent := service.MyService.System().GetCpuPercent()

```

This pattern provides type-safe, compile-time checked communication with minimal overhead.

### External Gateway Integration

For operations requiring interaction with the CasaOS-Common management component, the repository exposes `Gateway()`, which returns an `external.ManagementService`. This service handles route creation, port configuration, and other system-level networking tasks:

```go
response, err := service.MyService.Gateway().CreateRoute(&model.Route{
    Path:   "/v2/app",
    Target: "localhost:8080",
})

```

### Asynchronous Event Distribution

For decoupled, asynchronous communication, services utilize the **CasaOS Message Bus**. The `NotifyServer` publishes events through a generated OpenAPI client ([`codegen/message_bus/api.go`](https://github.com/IceWhaleTech/CasaOS/blob/main/codegen/message_bus/api.go)), allowing cross-service and cross-process event distribution:

```go
func (i *notifyServer) SendNotify(name string, message map[string]interface{}) {
    response, err := MyService.MessageBus().PublishEventWithResponse(
        context.Background(),
        common.SERVICENAME,
        name,
        message,
    )
    // ... handle response
}

```

Simultaneously, the notify service maintains active WebSocket connections (`WebSocketConns`) to push real-time notifications to connected clients.

### Shared In-Memory Caching

Services share a global cache instance (`service.Cache`) backed by `go-cache`. This enables cheap, in-process data sharing for frequently accessed, ephemeral data such as thermal zone paths and remote version information:

```go
// In service/casa.go
Cache.Set(keyName, version, time.Minute*20)

```

## Practical Implementation Example

The following example demonstrates initializing the service layer and utilizing multiple communication patterns:

```go
package main

import (
    "github.com/IceWhaleTech/CasaOS/service"
    "github.com/IceWhaleTech/CasaOS/pkg/config"
)

func main() {
    // Initialize the global repository (normally performed in main.go)
    db := /* gorm DB */ nil
    service.MyService = service.NewService(db, config.CommonInfo.RuntimePath)

    // Direct method call: Fetch CPU utilization
    cpuPct := service.MyService.System().GetCpuPercent()
    println("Current CPU %:", cpuPct)

    // Asynchronous event: Broadcast notification via Message Bus
    msg := map[string]interface{}{
        "title": "System Status",
        "body":  "CasaOS is operational",
    }
    service.MyService.Notify().SendNotify("casaos:info", msg)
}

```

This code performs a synchronous hardware query through `SystemService` and publishes an asynchronous event through `NotifyServer`, illustrating the dual communication models available within the architecture.

## Key Source Files to Explore

Understanding the CasaOS service layer architecture requires examining these critical files:

- **[`service/service.go`](https://github.com/IceWhaleTech/CasaOS/blob/main/service/service.go)**: Central repository definition, `Repository` interface, and service wiring logic.
- **[`service/system.go`](https://github.com/IceWhaleTech/CasaOS/blob/main/service/system.go)**: Core system operations including hardware statistics and power management.
- **[`service/notify.go`](https://github.com/IceWhaleTech/CasaOS/blob/main/service/notify.go)**: Notification handling, Message Bus publishing, and WebSocket connection management.
- **[`service/casa.go`](https://github.com/IceWhaleTech/CasaOS/blob/main/service/casa.go)**: Remote version checking with caching implementation.
- **[`service/connections.go`](https://github.com/IceWhaleTech/CasaOS/blob/main/service/connections.go)**: Database-backed service example for managing CIFS mounts.
- **[`main/main.go`](https://github.com/IceWhaleTech/CasaOS/blob/main/main/main.go)**: Application bootstrap that instantiates `MyService` and initializes dependencies.
- **[`route/v1/system.go`](https://github.com/IceWhaleTech/CasaOS/blob/main/route/v1/system.go)**: REST handlers demonstrating service consumption patterns.
- **[`codegen/message_bus/api.go`](https://github.com/IceWhaleTech/CasaOS/blob/main/codegen/message_bus/api.go)**: Generated OpenAPI client for Message Bus communication.

## Summary

- **Repository Pattern**: CasaOS uses a singleton `Repository` interface (`service.MyService`) to aggregate all domain services, providing a unified access point throughout the application.
- **Synchronous Communication**: Direct Go method calls via the singleton offer type-safe, high-performance interaction between HTTP handlers and business logic.
- **Asynchronous Messaging**: The Message Bus client enables decoupled event distribution across services and processes, while WebSocket connections provide real-time client notifications.
- **External Integration**: The `Gateway` service abstracts communication with the CasaOS-Common management component for network and routing operations.
- **Shared Resources**: A global `go-cache` instance (`service.Cache`) provides in-process caching accessible to all services.

## Frequently Asked Questions

### What architectural pattern does CasaOS use for its service layer?

CasaOS implements a **repository-style service layer** combined with the **singleton pattern**. The `Repository` interface defined in [`service/service.go`](https://github.com/IceWhaleTech/CasaOS/blob/main/service/service.go) acts as a service locator, exposing accessor methods for all concrete services. A global variable `service.MyService` holds the single instance initialized at startup, ensuring consistent state and resource sharing across the application.

### How do HTTP handlers access business logic in CasaOS?

HTTP handlers access business logic by importing the `service` package and invoking methods through the global `service.MyService` singleton. For example, a handler might call `service.MyService.System().GetCpuPercent()` to retrieve hardware statistics or `service.MyService.Casa().GetCasaosVersion()` to check for updates. This approach keeps handlers thin and delegates all domain logic to the service layer.

### What is the role of the Message Bus in CasaOS architecture?

The Message Bus provides **asynchronous, decoupled communication** between services and external components. Implemented via a generated OpenAPI client in [`codegen/message_bus/api.go`](https://github.com/IceWhaleTech/CasaOS/blob/main/codegen/message_bus/api.go), it allows services like `NotifyServer` to publish events using `PublishEventWithResponse()`. This enables cross-service notifications without direct method coupling, supporting event-driven workflows and integration with external CasaOS components.

### How does CasaOS deliver real-time notifications to web clients?

Real-time notifications flow through two pathways: first, the `NotifyServer` publishes events to the Message Bus for system-wide distribution; second, it maintains a slice of active WebSocket connections (`WebSocketConns`) and broadcasts messages directly to connected clients. This dual approach ensures both internal service awareness and immediate user interface updates.