# Turbine A modular service framework. ## Launchpad (Process Manager) The `launchpad` is a CLI tool located in `pkg/launchpad` designed to simplify development and production workflows for the entire Turbine project. It acts as a process manager that can run all defined services concurrently for development and generate a `docker-compose.yml` file for production deployments. ### Configuration (`launchpad.toml`) The launchpad is configured via a `launchpad.toml` file in the project root. This file defines all the services, their configurations, and the networks they use. **`launchpad.toml` example:** ```toml # Defines variables required by the configuration. # These should be supplied in a .env file. [variables] required = ["CACHE_PASSWORD", "QUEUE_PASSWORD", "RING_IMAGE", "RING_PORT"] # Defines docker networks. [networks] aspire = {} # Service definitions [[services]] name = "cache" type = "docker" # For third-party docker images [services.prod] image = "docker.io/library/redis:7.4" command = ["/bin/sh", "-c", "redis-server --requirepass $$REDIS_PASSWORD"] environment = ["REDIS_PASSWORD=${CACHE_PASSWORD}"] expose = ["6379"] networks = ["aspire"] [[services]] name = "ring" type = "dotnet" path = "../turbine-dotnet-services/ring" [services.dev] command = "dotnet watch run" [services.prod] image = "${RING_IMAGE}" environment = [ "HTTP_PORTS=${RING_PORT}", "ConnectionStrings__cache=cache:6379,password=${CACHE_PASSWORD}", ] volumes = ["./keys:/app/keys", "./settings/ring.json:/app/appsettings.json"] expose = ["${RING_PORT}", "5001"] networks = ["aspire"] depends_on = ["cache", "queue"] ``` ### Environment Variables (`.env`) For the `deploy` command to work, you must create a `.env` file in the project root containing the variables defined in `launchpad.toml`. An example is provided in `.env.example`. ### Commands To use the launchpad, run its `main.go` file with one of the following commands: #### Development (`dev`) Starts all services defined in `launchpad.toml` in development mode. Each service runs in a separate process, and their logs are streamed to the console with colored prefixes. A single `Ctrl+C` will gracefully shut down all services. ```bash go run ./pkg/launchpad/main.go dev ``` #### Production Deployment (`deploy`) Generates a `docker-compose.yml` file in the project root based on the `prod` configuration of all services in `launchpad.toml`. It substitutes variables from your `.env` file. This file can be used to build and run all services as Docker containers. ```bash go run ./pkg/launchpad/main.go deploy ``` ## Registrar The Registrar is the service discovery system of the DysonNetwork. Here are a port to the Golang in order to support other Golang services. To use the system, try build with these API: ```go package main import ( "log" "os" "os/signal" "syscall" "yourmodule/registry" ) func main() { endpoints := []string{"localhost:2379"} registrar, err := registry.NewServiceRegistrar(endpoints) if err != nil { log.Fatalf("Error creating registrar: %v", err) } serviceName := "orders" host := "10.0.0.5" port := 5000 ttl := int64(30) err = registrar.Register(serviceName, "http", "instance-1", host, port, ttl) if err != nil { log.Fatalf("Register error: %v", err) } log.Println("Service registered") // Wait for termination stop := make(chan os.Signal, 1) signal.Notify(stop, syscall.SIGINT, syscall.SIGTERM) <-stop err = registrar.Deregister() if err != nil { log.Printf("Deregister error: %v", err) } else { log.Println("Service deregistered") } } ``` ## Gateway The gateway is the entry point for all requests. It uses the `registrar` to discover services in real-time from etcd and forwards requests to the appropriate service instances. ### Features - **Service Discovery**: Automatically discovers `http` services from etcd. - **Dynamic Routing**: Maintains an in-memory routing table that is automatically updated when services are added or removed. - **Request Proxying**: Forwards incoming requests to the correct service instance based on the URL path (`//...`). - **Load Balancing**: Implements round-robin load balancing across service instances. - **Route Overrides**: Allows for custom routing rules to be defined in the configuration file. ### Configuration The gateway is configured via a `settings.toml` file located in the same directory. ```toml # The address the gateway will listen on listen = ":8080" # ETCD configuration for service discovery [etcd] endpoints = ["127.0.0.1:2379"] # Set to true if your etcd server does not use TLS insecure = true # Custom route overrides # The key is the incoming path prefix. # The value is the destination in the format "//" [routes] "/websocket" = "/chatter/ws" ``` ## Config Service The config service provides a centralized location for other services to fetch their configuration. This is useful for managing connection strings, feature flags, and other shared parameters without hardcoding them into each service. ### Usage The config service reads a `shared_config.toml` file from its own directory (`pkg/config`) and serves it as a JSON object over a simple HTTP endpoint. To retrieve the configuration, other services can make a GET request to the gateway at `/config`. The gateway will route the request to an available instance of the config service. **Example with curl:** ```bash curl http://localhost:8080/config ``` **Expected Response (JSON):** ```json { "database": { "connection_string": "postgres://user:password@db-host:5432/mydatabase?sslmode=require" }, "redis": { "address": "redis-host:6379" } } ```