Skip to content

Latest commit

 

History

History
263 lines (202 loc) · 5.79 KB

File metadata and controls

263 lines (202 loc) · 5.79 KB
layout page
title Getting Started
permalink /getting-started/

Getting Started with Forge

Get up and running with the Forge framework in just a few minutes.

Installation

go mod init my-service
go get github.com/datariot/forge

Your First Service

Create a simple service with health checks and graceful shutdown:

package main

import (
    "context"
    "log"

    "github.com/datariot/forge/config"
    "github.com/datariot/forge/framework"
    "github.com/datariot/forge/health"
)

// UserService implements the Component interface
type UserService struct {
    config *config.BaseConfig
}

func (s *UserService) Start(ctx context.Context) error {
    log.Printf("UserService started")
    return nil
}

func (s *UserService) Stop(ctx context.Context) error {
    log.Printf("UserService stopping gracefully")
    return nil
}

func (s *UserService) HealthChecks() []health.Check {
    return []health.Check{
        health.NewAlwaysHealthyCheck("user-service"),
    }
}

func main() {
    // Load configuration
    cfg := config.DefaultBaseConfig()
    cfg.ServiceName = "user-service"
    cfg.AppEnv = "development"

    // Validate configuration
    if err := cfg.Validate(); err != nil {
        log.Fatalf("Configuration validation failed: %v", err)
    }

    // Create application
    app, err := framework.New(
        framework.WithConfig(&cfg),
        framework.WithVersion("1.0.0"),
        framework.WithComponent(&UserService{config: &cfg}),
        framework.WithHealthContributor(&UserService{config: &cfg}),
    )
    if err != nil {
        log.Fatalf("Failed to create application: %v", err)
    }

    // Run the service
    log.Printf("Starting %s...", cfg.ServiceName)
    if err := app.Run(context.Background()); err != nil {
        log.Fatalf("Application failed: %v", err)
    }
}

Running Your Service

go run main.go

Your service will start with:

  • gRPC server on :8080
  • HTTP health endpoints on :8081
    • http://localhost:8081/health - Overall health
    • http://localhost:8081/health/ready - Readiness probe
    • http://localhost:8081/health/live - Liveness probe
    • http://localhost:8081/metrics - Prometheus metrics

Adding Database Connectivity

Add PostgreSQL with automatic health checks:

import (
    "github.com/datariot/forge/bundles/postgresql"
)

func main() {
    // Configure database
    dbConfig := postgresql.Config{
        DatabaseURL: "postgres://user:pass@localhost:5432/mydb?sslmode=require",
        MaxOpenConns: 25,
        MaxIdleConns: 10,
        ConnMaxLifetime: 30 * time.Minute,
    }

    pgBundle := postgresql.NewBundle(dbConfig)

    app, err := framework.New(
        framework.WithConfig(&cfg),
        framework.WithBundle(pgBundle), // Add database bundle
        framework.WithComponent(service),
    )
}

Adding Caching

Add Redis for caching and messaging:

import (
    "github.com/datariot/forge/bundles/redis"
)

func main() {
    // Configure Redis
    redisConfig := redis.Config{
        RedisURL: "redis://localhost:6379/0",
        PoolSize: 10,
        MinIdleConns: 2,
    }

    redisBundle := redis.NewBundle(redisConfig)

    app, err := framework.New(
        framework.WithConfig(&cfg),
        framework.WithBundle(redisBundle), // Add caching bundle
        framework.WithComponent(service),
    )

    // Use Redis in your service
    cache := redisBundle.Cache()
    cache.Set(ctx, "user:123", userData, 1*time.Hour)
}

Adding Authentication

Secure service-to-service communication with JWT:

import (
    "github.com/datariot/forge/bundles/jwt"
)

func main() {
    // Configure JWT authentication
    jwtConfig := jwt.Config{
        SecretKey: []byte("your-32-plus-character-secret-key"),
        Issuer: "auth-service",
        Audience: "my-services",
        ServiceName: cfg.ServiceName,
    }

    jwtBundle := jwt.NewBundle(jwtConfig)

    app, err := framework.New(
        framework.WithConfig(&cfg),
        framework.WithBundle(jwtBundle), // Add authentication
        framework.WithUnaryInterceptor(jwtBundle.UnaryServerInterceptor()),
        framework.WithComponent(service),
    )
}

Environment Configuration

Configure your service using environment variables:

# Service configuration
export SERVICE_NAME="user-service"
export APP_ENV="production"
export GRPC_ADDR=":8080"
export HTTP_ADDR=":8081"
export LOG_LEVEL="info"

# Database configuration
export DATABASE_URL="postgres://user:pass@db-host:5432/mydb?sslmode=require"

# Redis configuration
export REDIS_URL="redis://redis-host:6379/0"

# JWT authentication
export JWT_SECRET="your-production-secret-key-32-characters-minimum"
export JWT_ISSUER="auth-service"
export JWT_AUDIENCE="production-services"

# Run your service
go run main.go

Next Steps

Key Concepts

Components

Components are your business logic that implement the Component interface:

type Component interface {
    Start(ctx context.Context) error
    Stop(ctx context.Context) error
}

Bundles

Bundles are pre-built integrations that add functionality to your application:

type Bundle interface {
    Name() string
    Initialize(app *App) error
}

Health Checks

Implement health checks for monitoring and alerting:

type HealthContributor interface {
    HealthChecks() []health.Check
}

Application Lifecycle

Forge handles sophisticated startup and shutdown:

  1. Initialize configuration and logging
  2. Initialize bundles (PostgreSQL, Redis, etc.)
  3. Start gRPC and HTTP servers
  4. Start your components
  5. Mark service as ready
  6. Handle graceful shutdown in reverse order