### Example Router Setup and Route Initialization Source: https://github.com/bk1031/rincon/blob/main/_autodocs/api-reference/http-handlers.md Demonstrates the typical usage pattern for setting up the Gin router and initializing API routes. This is a common starting point for running the application. ```go router := api.SetupRouter() api.InitializeRoutes(router) err := router.Run(":10311") ``` -------------------------------- ### Application Startup Flow Source: https://github.com/bk1031/rincon/blob/main/_autodocs/MODULES.md Illustrates the sequence of operations during the application's startup process, from initialization to server start. ```go main.go ↓ config.PrintStartupBanner() ↓ utils.InitializeLogger() ↓ utils.VerifyConfig() [Applies defaults, validates] ↓ database.InitializeDB() [Local or SQL based on config] ↓ service.RegisterSelf() [Register Rincon itself] ↓ service.InitializeHeartbeat() [Start health checks] ↓ router := api.SetupRouter() [Create HTTP router] ↓ api.InitializeRoutes(router) [Register all endpoints] ↓ router.Run(": ``` ```go " + config.Port) [Start HTTP server] ``` -------------------------------- ### Service Routes Response Example Source: https://github.com/bk1031/rincon/blob/main/_autodocs/endpoints.md An example of the response when fetching routes for a service, showing an array of route objects. ```json [ { "id": "/users-[GET,POST]", "route": "/users", "method": "GET,POST", "service_name": "user_service", "created_at": "2025-03-22T00:07:40.807812-07:00" }, { "id": "/users/*-[GET]", "route": "/users/*", "method": "GET", "service_name": "user_service", "created_at": "2025-03-22T00:07:40.807812-07:00" } ] ``` -------------------------------- ### Example Valid Authorization Header Source: https://github.com/bk1031/rincon/blob/main/_autodocs/api-reference/http-handlers.md Illustrates the correct format for the Authorization header when using Basic Authentication. The example shows a Base64 encoded string that decodes to 'admin:admin'. ```text Authorization: Basic YWRtaW46YWRtaW4= (Decodes to: admin:admin) ``` -------------------------------- ### Debug-Level Route Graph Output Example Source: https://github.com/bk1031/rincon/blob/main/_autodocs/errors.md This is an example of the debug-level output generated when the environment is set to DEV and a GET request is made to /rincon/match. It helps in debugging route matching by showing the graph structure and traversal steps. ```log 2025-03-22T00:07:37.383-0700 DEBUG service/route.go:234 Matching route /rincon/services/123456/routes 2025-03-22T00:07:37.383-0700 DEBUG service/route.go:263 Traversing graph with path "" and route "/rincon/services/123456/routes" 2025-03-22T00:07:37.383-0700 DEBUG service/route.go:277 Child path "" exists 2025-03-22T00:07:37.386-0700 DEBUG service/route.go:252 Matched route /rincon/services/123456/routes to /rincon/services/** for service rincon (557684) ``` -------------------------------- ### Client Heartbeat Service Registration Example Source: https://github.com/bk1031/rincon/blob/main/_autodocs/api-reference/heartbeat.md Example of a service implementing client heartbeat by periodically updating its registration with Rincon. Requires periodic calls to CreateService. ```go package main import ( "time" "rincon/model" "rincon/service" ) func main() { // Register service svc := model.Service{ Name: "my_service", Version: "1.0.0", Endpoint: "http://localhost:8080", HealthCheck: "http://localhost:8080/health", } service.CreateService(svc) // Ping Rincon every 5 seconds to stay registered ticker := time.NewTicker(5 * time.Second) for range ticker.C { svc.UpdatedAt = time.Now() service.CreateService(svc) } } ``` -------------------------------- ### Example cURL with Basic Authentication Source: https://github.com/bk1031/rincon/blob/main/_autodocs/configuration.md Demonstrates how to use curl with Basic Authentication credentials to access Rincon services. ```bash curl -u myuser:password http://localhost:10311/rincon/services ``` -------------------------------- ### Data Flow Example: Service Registration Source: https://github.com/bk1031/rincon/blob/main/_autodocs/MODULES.md Explains the process of registering a new service, including request handling, validation, storage, and response. ```go POST /rincon/services ↓ api.CreateService() [Handler] ↓ c.ShouldBindJSON(&input) [Validate JSON] ↓ service.CreateService(input) [Business logic] ↓ Normalize name, generate ID ↓ service.GetServiceByEndpoint() [Check if exists] ↓ database.DB.Create() or database.Local.Services append [Store] ↓ service.GetServiceByEndpoint() [Retrieve to return] ↓ c.JSON(200, result) [Return to client] ``` -------------------------------- ### Registered Route Object Example Source: https://github.com/bk1031/rincon/blob/main/_autodocs/endpoints.md This is an example of a successful response when a route is registered. It includes the unique ID, route details, service name, and creation timestamp. ```json { "id": "/users-[GET,POST]", "route": "/users", "method": "GET,POST", "service_name": "user_service", "created_at": "2025-03-22T00:07:40.807812-07:00" } ``` -------------------------------- ### Wildcard Route Example: All Wildcard Source: https://github.com/bk1031/rincon/blob/main/README.md Demonstrates the use of the '/**' wildcard for matching any remaining path segments. ```text /users/** --- /users/123 /users/abc/edit /users/a1b2c3/account/settings ``` ```text /users/*/profile/** --- /users/123/profile/edit /users/abc/profile/settings/notifications ``` -------------------------------- ### Wildcard Route Example: Any Wildcard Source: https://github.com/bk1031/rincon/blob/main/README.md Demonstrates the use of the '/*' wildcard for matching any single path segment. ```text /users/* --- /users/123 /users/abc ``` ```text /users/*/profile --- /users/123/profile /users/abc/profile ``` -------------------------------- ### Setup Gin Router Source: https://github.com/bk1031/rincon/blob/main/_autodocs/api-reference/http-handlers.md Creates and configures the Gin router with essential middleware like CORS and authentication. Sets Gin to ReleaseMode for production environments. ```go func SetupRouter() *gin.Engine ``` -------------------------------- ### Data Flow Example: Route Matching Source: https://github.com/bk1031/rincon/blob/main/_autodocs/MODULES.md Illustrates the flow for matching a route, including request parsing, graph traversal, load balancing, and service selection. ```go GET /rincon/match?route=users&method=GET ↓ api.MatchRoute() [Handler] ↓ Normalize path and method ↓ service.MatchRoute() [Business logic] ↓ service.GetRouteGraph() [Build route graph] ↓ service.TraverseGraph() [Match against graph] ↓ service.LoadBalance() [Select service instance] ↓ service.RandomSelector() [Pick random instance] ↓ c.JSON(200, service) [Return service to client] ``` -------------------------------- ### MatchRoute Handler Example Flow Source: https://github.com/bk1031/rincon/blob/main/_autodocs/api-reference/http-handlers.md Illustrates the request flow for matching a route to a service. Includes request normalization and the matching process. ```text Request: GET /rincon/match?route=users/123&method=GET ↓ Normalize: route="users/123", method="GET" ↓ Match route against graph ↓ Load balance across service instances ↓ Return Service object ``` -------------------------------- ### Get All Registered Routes Source: https://github.com/bk1031/rincon/blob/main/_autodocs/api-reference/route.md Retrieves all registered routes from the registry. Use this to get a complete list of all defined routes. ```Go routes := service.GetAllRoutes() for _, route := range routes { log.Printf("Route: %s [%s] -> %s", route.Route, route.Method, route.ServiceName) } ``` -------------------------------- ### Docker Compose Setup for Rincon and PostgreSQL Source: https://github.com/bk1031/rincon/blob/main/_autodocs/configuration.md Defines a Docker Compose setup for running Rincon with a PostgreSQL database, including environment variables for both services. ```yaml version: '3.8' services: postgres: image: postgres:15 environment: POSTGRES_DB: rincon POSTGRES_USER: rincon POSTGRES_PASSWORD: password ports: - "5432:5432" rincon: image: bk1031/rincon:latest environment: PORT: "10311" ENV: "PROD" STORAGE_MODE: "sql" DB_DRIVER: "postgres" DB_HOST: "postgres" DB_PORT: "5432" DB_NAME: "rincon" DB_USER: "rincon" DB_PASSWORD: "password" AUTH_USER: "admin" AUTH_PASSWORD: "admin" HEARTBEAT_TYPE: "server" HEARTBEAT_INTERVAL: "10" ports: - "10311:10311" depends_on: - postgres ``` -------------------------------- ### Route Object Example Source: https://github.com/bk1031/rincon/blob/main/_autodocs/endpoints.md This is an example of a Route object returned when filtering routes. It includes details like route path, methods, and associated service name. ```json [ { "id": "/users-[GET,POST]", "route": "/users", "method": "GET,POST", "service_name": "user_service", "created_at": "2025-03-22T00:07:40.807812-07:00" } ] ``` -------------------------------- ### Match a Route to a Service Source: https://github.com/bk1031/rincon/blob/main/README.md Finds a registered service that matches the '/service' route and 'GET' method. ```bash curl "http://localhost:10311/rincon/match?route=service&method=GET" ``` -------------------------------- ### Get All Routes Source: https://github.com/bk1031/rincon/blob/main/_autodocs/endpoints.md Retrieve a list of all registered routes. No authentication is required for this endpoint. ```bash curl 'http://localhost:10311/rincon/routes' ``` -------------------------------- ### Route Conflict Error Example Source: https://github.com/bk1031/rincon/blob/main/_autodocs/errors.md This example shows a request that fails due to a route conflict. The error message indicates that the specified route and method already exist for another service. ```bash curl -X POST http://localhost:10311/rincon/routes \ -H 'Content-Type: application/json' \ -H 'Authorization: Basic YWRtaW46YWRtaW4=' \ -d '{ "route": "/users", "method": "GET", # ❌ Conflicts with ServiceA "service_name": "other_service" }' ``` ```json { "message": "route with id /users-[GET] overlaps with existing routes [[GET] /users (service_a)]" } ``` -------------------------------- ### Run Rincon with Docker Source: https://github.com/bk1031/rincon/blob/main/README.md Starts the Rincon service in detached mode, exposing the default port. ```bash $ docker run -d -p 10311:10311 bk1031/rincon:latest ``` -------------------------------- ### GetAllServices Handler Source: https://github.com/bk1031/rincon/blob/main/_autodocs/api-reference/http-handlers.md Lists all registered service instances. This handler is accessible via the GET /rincon/services endpoint and does not require authentication. ```go func GetAllServices(c *gin.Context) ``` -------------------------------- ### Get Routes by Path Pattern Source: https://github.com/bk1031/rincon/blob/main/_autodocs/api-reference/route.md Retrieves all routes that match a specific path pattern. The leading/trailing slashes in the provided route are automatically normalized. ```Go routes := service.GetRoutesByRoute("/users") log.Printf("Found %d routes for /users", len(routes)) ``` -------------------------------- ### Get Routes by Service Name Source: https://github.com/bk1031/rincon/blob/main/_autodocs/api-reference/route.md Retrieves all routes registered for a specific service. The service name is normalized to lowercase with underscores. ```Go routes := service.GetRoutesByServiceName("user_service") log.Printf("Service has %d routes", len(routes)) ``` -------------------------------- ### Register Route with Invalid HTTP Method Source: https://github.com/bk1031/rincon/blob/main/_autodocs/errors.md Shows an example of trying to register a route with an unsupported HTTP method and the resulting error message. ```bash # This will fail: curl -X POST http://localhost:10311/rincon/routes \ -H 'Content-Type: application/json' \ -H 'Authorization: Basic YWRtaW46YWRtaW4=' \ -d '{ "route": "/users", "method": "INVALID", # ❌ Not in ValidMethods "service_name": "user_service" }' # Response: { "message": "invalid method INVALID" } ``` -------------------------------- ### Error: Missing Method Parameter for Match Source: https://github.com/bk1031/rincon/blob/main/_autodocs/errors.md This example demonstrates a request to the /rincon/match endpoint that fails due to a missing 'method' query parameter. The API responds with a 400 Bad Request status. ```bash curl 'http://localhost:10311/rincon/match?route=users' # Response: { "message": "Method query is required" } ``` -------------------------------- ### Error: Route Not Found by Path and Service Source: https://github.com/bk1031/rincon/blob/main/_autodocs/errors.md This example demonstrates a request to find routes that fails because the specified route path and service name do not match any registered route. The API returns a 404 Not Found status. ```bash curl 'http://localhost:10311/rincon/routes?route=/fake&service=nonexistent' # Response: { "message": "No route /fake for service nonexistent found" } ``` -------------------------------- ### Error: Route Not Found by Path and Method Source: https://github.com/bk1031/rincon/blob/main/_autodocs/errors.md This example shows a request to find routes that fails because the specified route path and HTTP method do not match any registered route. The API returns a 404 Not Found status. ```bash curl 'http://localhost:10311/rincon/routes?route=/fake&method=DELETE' # Response: { "message": "No route [DELETE] /fake found" } ``` -------------------------------- ### Get Single Route by Path and Method Source: https://github.com/bk1031/rincon/blob/main/_autodocs/api-reference/route.md Retrieves a single route based on its path and HTTP method. Returns an empty struct if no match is found. ```Go route := service.GetRouteByRouteAndMethod("/users", "GET") if route.ID != "" { log.Printf("Found route: %s", route.ID) } ``` -------------------------------- ### Error: Service Not Found by ID Source: https://github.com/bk1031/rincon/blob/main/_autodocs/errors.md This example shows a request to retrieve service details using an ID that does not exist. The API returns a 404 Not Found status with a specific error message. ```bash curl 'http://localhost:10311/rincon/services/999999' # Response: { "message": "No service with id 999999 found" } ``` -------------------------------- ### Get Single Route by Path and Service Source: https://github.com/bk1031/rincon/blob/main/_autodocs/api-reference/route.md Retrieves a single route based on its path and service name. Returns an empty struct if no match is found. ```Go route := service.GetRouteByRouteAndService("/users", "user_service") if route.ID != "" { log.Printf("Service %s handles %s", route.ServiceName, route.Route) } ``` -------------------------------- ### Get Total Service Instance Count Source: https://github.com/bk1031/rincon/blob/main/_autodocs/api-reference/service.md Returns the total number of registered service instances. Use this to quickly determine the scale of your service deployments. ```Go count := service.GetNumServices() log.Printf("Total service instances: %d", count) ``` -------------------------------- ### HTTP Request Handlers Source: https://github.com/bk1031/rincon/blob/main/_autodocs/INDEX.md Details the implementation of HTTP endpoint handlers and middleware. This section covers setup, authentication, and specific handlers for services and routes. ```APIDOC ## HTTP Request Handlers ### Description Implementation details of HTTP endpoint handlers and middleware used within Rincon. ### Middleware & Setup - `SetupRouter()` - Creates and configures the main router. - `InitializeRoutes(router)` - Registers all defined endpoints with the router. - `AuthMiddleware()` - Applies basic authentication to requests. ### Service Handlers - `Ping(c)` - Handles health check requests. - `GetAllServices(c)` - Retrieves a list of all registered services. - `GetService(c)` - Retrieves details for a specific service. - `CreateService(c)` - Registers a new service. - `RemoveService(c)` - Deletes a service. ### Route Handlers - `GetRoute(c)` - Queries for route information. - `CreateRoute(c)` - Registers a new route. - `GetRoutesForService(c)` - Lists all routes associated with a specific service. - `MatchRoute(c)` - Matches an incoming request to a configured route. ``` -------------------------------- ### Error: No Service Found for Matched Route Source: https://github.com/bk1031/rincon/blob/main/_autodocs/errors.md This example illustrates a scenario where a request to /rincon/match is made, but no registered route matches the provided path and method. The API returns a 404 Not Found status. ```bash curl 'http://localhost:10311/rincon/match?route=nonexistent&method=GET' # Response: { "message": "No route [GET] /nonexistent found" } ``` -------------------------------- ### Error: Missing Route Parameter for Match Source: https://github.com/bk1031/rincon/blob/main/_autodocs/errors.md This example shows a request to the /rincon/match endpoint that fails because the required 'route' query parameter is missing. The API returns a 400 Bad Request status. ```bash curl 'http://localhost:10311/rincon/match?method=GET' # Response: { "message": "Route query is required" } ``` -------------------------------- ### Register a New Route Source: https://github.com/bk1031/rincon/blob/main/_autodocs/endpoints.md Use this snippet to register a new route for a service. Ensure the route path starts with '/' and does not end with '/'. The request body specifies the route, allowed HTTP methods, and the service name. ```bash curl -X POST http://localhost:10311/rincon/routes \ -H 'Content-Type: application/json' \ -H 'Authorization: Basic YWRtaW46YWRtaW4=' \ -d '{ "route": "/users", "method": "GET,POST", "service_name": "User Service" }' ``` -------------------------------- ### Minimal Local Development Configuration Source: https://github.com/bk1031/rincon/blob/main/_autodocs/configuration.md Sets up minimal configuration for local development, including environment and storage mode. ```bash export ENV=DEV export PORT=10311 export STORAGE_MODE=local ``` -------------------------------- ### SetupRouter Source: https://github.com/bk1031/rincon/blob/main/_autodocs/api-reference/http-handlers.md Creates and configures the Gin router with essential middleware like CORS and authentication. It sets the Gin mode based on the environment and applies specific CORS configurations. ```APIDOC ## SetupRouter ### Description Creates and configures the Gin router with middleware. It sets the Gin mode to ReleaseMode if the environment is not 'DEV' and enables CORS with specific allowed methods, headers, and a max age of 12 hours. It also applies authentication middleware to protected operations. ### Method N/A (Go function) ### Endpoint N/A ### Returns - **`*gin.Engine`** - Configured Gin router instance ### Configuration Details - **Mode**: Sets Gin to ReleaseMode if ENV != "DEV" - **CORS Middleware**: Enables CORS for all origins with specific allowed methods, headers, max age, and credentials. - **Auth Middleware**: Applies Basic Auth to protected operations. ### Example Usage ```go router := api.SetupRouter() api.InitializeRoutes(router) err := router.Run(":10311") ``` ``` -------------------------------- ### Initialize Database Connection Source: https://github.com/bk1031/rincon/blob/main/_autodocs/api-reference/utilities.md Initializes the selected storage backend based on the STORAGE_MODE configuration. It calls InitializeSQL() for 'sql' or 'redis+sql', and InitializeLocal() for other modes. ```go func InitializeDB() { // ... } ``` ```go database.InitializeDB() // Database connection established ``` -------------------------------- ### Add SQL Migrations Source: https://github.com/bk1031/rincon/blob/main/_autodocs/MODULES.md Outlines the steps for adding SQL migrations, including model definition, database initialization updates, and configuration. ```go Add model struct to `model/` package with GORM tags Update `database/sql.go` InitializeSQL() AutoMigrate call Add config variables if new options needed ``` -------------------------------- ### Go: Route Matching with No Service Found Handling Source: https://github.com/bk1031/rincon/blob/main/_autodocs/errors.md This Go snippet demonstrates how to match a route for a given path and method, and how to handle the case where no matching service is found. It provides guidance on checking route registration, method handling, and service health. ```go svc := service.MatchRoute("users/123", "GET") if svc.ID == 0 { log.Println("No service found for GET /users/123") log.Println("Check that:") log.Println("1. Route is registered") log.Println("2. Service handles the HTTP method") log.Println("3. Service instance is healthy") return } log.Printf("Forward request to %s", svc.Endpoint) ``` -------------------------------- ### Rincon Service Object Structure Source: https://github.com/bk1031/rincon/blob/main/README.md Example of a Service object returned by Rincon after registration. ```json { "id": 820522, "name": "rincon", "version": "2.0.0", "endpoint": "http://localhost:10311", "health_check": "http://localhost:10311/rincon/ping", "updated_at": "2024-08-04T19:32:40.109239344-07:00", "created_at": "2024-08-04T19:32:40.109239386-07:00" } ``` -------------------------------- ### GET /rincon/services Source: https://github.com/bk1031/rincon/blob/main/_autodocs/endpoints.md Retrieves a list of all currently registered service instances within the Rincon registry. ```APIDOC ## GET /rincon/services ### Description List all registered service instances. ### Method GET ### Endpoint /rincon/services ### Parameters None ### Response (200 OK) Array of Service objects: - **id** (integer) - Service instance ID - **name** (string) - Normalized service name - **version** (string) - Service version - **endpoint** (string) - Service endpoint URL - **health_check** (string) - Health check endpoint URL - **updated_at** (string) - ISO 8601 timestamp - **created_at** (string) - ISO 8601 timestamp ### Response Example [ { "id": 941815, "name": "rincon", "version": "2.2.0", "endpoint": "http://localhost:10311", "health_check": "http://localhost:10311/rincon/ping", "updated_at": "2025-03-22T00:07:40.703258671-07:00", "created_at": "2025-03-22T00:07:40.703258754-07:00" } ] ``` -------------------------------- ### Add New Load Balancing Strategy Source: https://github.com/bk1031/rincon/blob/main/_autodocs/MODULES.md Demonstrates how to add a new load balancing strategy by implementing a function and updating the LoadBalance logic. ```go func RoundRobinSelector(services []model.Service) model.Service { ... } ``` -------------------------------- ### Route Stacking: Wildcard Method Source: https://github.com/bk1031/rincon/blob/main/README.md Demonstrates route stacking when one of the methods is a wildcard ('*'). The wildcard method takes precedence. ```c New York: /users [*] New York: /users [POST] --- New York: /users [*] ``` -------------------------------- ### GET /rincon/ping Source: https://github.com/bk1031/rincon/blob/main/_autodocs/endpoints.md Performs a health check on the Rincon service and provides status information about registered services and routes. ```APIDOC ## GET /rincon/ping ### Description Health check and registry status endpoint. ### Method GET ### Endpoint /rincon/ping ### Parameters None ### Response (200 OK) - **message** (string) - Status message (e.g., "Rincon v2.2.0 is online!") - **services** (integer) - Count of unique service names - **routes** (integer) - Total count of registered routes ### Response Example { "message": "Rincon v2.2.0 is online!", "services": 3, "routes": 12 } ``` -------------------------------- ### InitializeDB Source: https://github.com/bk1031/rincon/blob/main/_autodocs/api-reference/utilities.md Initializes the selected storage backend based on the STORAGE_MODE configuration. It can either call InitializeSQL() for SQL or Redis+SQL modes, or InitializeLocal() for other modes. ```APIDOC ## InitializeDB ### Description Initializes the selected storage backend. Behavior depends on the STORAGE_MODE configuration. ### Function Signature ```go func InitializeDB() ``` ### Behavior - If STORAGE_MODE is `"sql"` or `"redis+sql"`: Calls `InitializeSQL()`. - Otherwise: Calls `InitializeLocal()`. ### Example Usage ```go database.InitializeDB() // Database connection established ``` ``` -------------------------------- ### Initialize SQL Database Storage Source: https://github.com/bk1031/rincon/blob/main/_autodocs/api-reference/utilities.md Initializes SQL database storage with automatic migration. It attempts to connect, retries on failure, falls back to InitializeLocal() after multiple failures, and runs GORM AutoMigrate upon successful connection. ```go func InitializeSQL() { // ... } ``` ```go database.InitializeSQL() // SQL database connected and migrated log.Println("Database ready") ``` -------------------------------- ### Handle Empty Service Name Error Source: https://github.com/bk1031/rincon/blob/main/_autodocs/errors.md Demonstrates how to check for and handle an empty service name error when creating a service. ```go svc := model.Service{ Version: "1.0.0", Endpoint: "http://localhost:8080", HealthCheck: "http://localhost:8080/health", // Name is empty } _, err := service.CreateService(svc) if err != nil { if err.Error() == "service name cannot be empty" { log.Println("Service name is required") } } ``` -------------------------------- ### Initialize Local In-Memory Storage Source: https://github.com/bk1031/rincon/blob/main/_autodocs/api-reference/utilities.md Initializes in-memory (local) storage. This is suitable for development and testing as data is lost on restart and has no external dependencies. ```go func InitializeLocal() { // ... } ``` ```go database.InitializeLocal() // In-memory storage ready log.Printf("Services: %d", len(database.Local.Services)) ``` -------------------------------- ### Get Total Number of Registered Routes Source: https://github.com/bk1031/rincon/blob/main/_autodocs/api-reference/route.md Returns the total count of registered routes. Useful for monitoring or quick checks. ```Go count := service.GetNumRoutes() log.Printf("Total routes: %d", count) ``` -------------------------------- ### GET /rincon/services/:name/routes Source: https://github.com/bk1031/rincon/blob/main/_autodocs/endpoints.md Retrieves all registered routes associated with a specific service. This is useful for inspecting the routing configuration for a given service. ```APIDOC ## GET /rincon/services/:name/routes ### Description Get all routes for a specific service. This endpoint allows you to retrieve a list of all routes that have been registered for a particular service. ### Method GET ### Endpoint /rincon/services/{name}/routes ### Parameters #### Path Parameters - **name** (string) - Yes - Service name ### Response #### Success Response (200 OK) Array of Route objects for the service. #### Response Example ```json [ { "id": "/users-[GET,POST]", "route": "/users", "method": "GET,POST", "service_name": "user_service", "created_at": "2025-03-22T00:07:40.807812-07:00" }, { "id": "/users/*-[GET]", "route": "/users/*", "method": "GET", "service_name": "user_service", "created_at": "2025-03-22T00:07:40.807812-07:00" } ] ``` ``` -------------------------------- ### GET /rincon/routes Source: https://github.com/bk1031/rincon/blob/main/_autodocs/endpoints.md Lists all registered routes or filters them based on route path, HTTP method, or service name. Authentication is not required. ```APIDOC ## GET /rincon/routes ### Description List or filter registered routes. ### Method GET ### Endpoint /rincon/routes ### Parameters #### Query Parameters - **route** (string) - No - Filter by route path (e.g., "/users") - **method** (string) - No - Filter by HTTP method (e.g., "GET") - **service** (string) - No - Filter by service name ### Response #### Success Response (200 OK) Array of Route objects or single Route object: - **id** (string) - Route ID in format `{route}-[{method}]` - **route** (string) - Route path - **method** (string) - HTTP method(s) - **service_name** (string) - Service name - **created_at** (string) - ISO 8601 timestamp #### Response Example ```json [ { "id": "/users-[GET,POST]", "route": "/users", "method": "GET,POST", "service_name": "user_service", "created_at": "2025-03-22T00:07:40.807812-07:00" } ] ``` #### Response (404 Not Found) If no matching route exists ``` -------------------------------- ### InitializeSQL Source: https://github.com/bk1031/rincon/blob/main/_autodocs/api-reference/utilities.md Initializes SQL database storage with automatic migration. It supports MySQL and PostgreSQL drivers and handles connection retries, falling back to InitializeLocal() on persistent failure. ```APIDOC ## InitializeSQL ### Description Initializes SQL database storage with automatic migration. This function attempts to connect to the database using the selected driver, retrying up to 5 times with 5-second intervals if the initial connection fails. If all retries fail, it falls back to `InitializeLocal()`. Upon successful connection, it runs GORM AutoMigrate for `Service`, `ServiceDependency`, and `Route` tables and sets the global `database.DB` variable. ### Function Signature ```go func InitializeSQL() ``` ### Behavior 1. Attempts to connect using the selected database driver. 2. If connection fails: - Retries up to 5 times with 5-second intervals. - After 5 failures, falls back to `InitializeLocal()`. 3. If connection succeeds: - Runs GORM AutoMigrate for `Service`, `ServiceDependency`, `Route`. - Sets the global `database.DB` variable. ### Supported Drivers - `"mysql"`: Connects using `ConnectMysql()` with configurable host/port/credentials. - `"postgres"`: Connects using `ConnectPostgres()` with configurable host/port/credentials. ### Automatically Created Tables - `{DB_TABLE_PREFIX}service` - Service registrations - `{DB_TABLE_PREFIX}service_dependency` - Service dependencies - `{DB_TABLE_PREFIX}route` - Route registrations ### Example Usage ```go database.InitializeSQL() // SQL database connected and migrated log.Println("Database ready") ``` ``` -------------------------------- ### Go: Service Registration with Error Handling Source: https://github.com/bk1031/rincon/blob/main/_autodocs/errors.md This Go snippet demonstrates how to register a service and handle potential errors, such as missing required fields. It uses a switch statement to catch specific error messages. ```go svc := model.Service{ Name: "my_service", Version: "1.0.0", Endpoint: "http://localhost:8080", HealthCheck: "http://localhost:8080/health", } created, err := service.CreateService(svc) if err != nil { switch err.Error() { case "service name cannot be empty": log.Fatal("Service name is required") case "service version cannot be empty": log.Fatal("Service version is required") case "service endpoint cannot be empty": log.Fatal("Service endpoint is required") case "service health check cannot be empty": log.Fatal("Service health check URL is required") default: log.Fatalf("Failed to register service: %v", err) } } log.Printf("Service registered with ID: %d", created.ID) ``` -------------------------------- ### Convenience Logging with SugarLogger Source: https://github.com/bk1031/rincon/blob/main/_autodocs/api-reference/utilities.md Uses Zap's SugarLogger for Printf-style logging. This offers a more familiar interface for common logging tasks. ```go // Printf-style logging utils.SugarLogger.Infof("Service %s started on %s", "user_service", "localhost:8080") utils.SugarLogger.Warnf("Health check failed after %d attempts", 3) utils.SugarLogger.Errorf("Database error: %v", err) // Output (DEV mode): // 2025-03-22T00:07:37.383-0700 INFO service/service.go:129 Service user_service started on localhost:8080 // 2025-03-22T00:07:37.456-0700 WARN service/heartbeat.go:82 Health check failed after 3 attempts // 2025-03-22T00:07:37.789-0700 ERROR service/heartbeat.go:86 Database error: connection refused ``` -------------------------------- ### Initialize API Routes Source: https://github.com/bk1031/rincon/blob/main/_autodocs/api-reference/http-handlers.md Registers all API endpoint handlers with the provided Gin router instance. This function defines the structure of the API by mapping HTTP methods and paths to specific handlers. ```go func InitializeRoutes(router *gin.Engine) ``` -------------------------------- ### Match Incoming Request to a Service Source: https://github.com/bk1031/rincon/blob/main/_autodocs/endpoints.md Use this endpoint to find a suitable service instance for an incoming request based on its path and method. The query parameters 'route' and 'method' are required. ```bash curl 'http://localhost:10311/rincon/match?route=users/123&method=GET' ``` -------------------------------- ### Retrieve All Registered Services Source: https://github.com/bk1031/rincon/blob/main/_autodocs/api-reference/service.md Fetches a list of all services currently registered in the Rincon registry. This is useful for getting an overview of all available service instances. ```Go package main import ( "log" "rincon/service" ) func main() { services := service.GetAllServices() for _, svc := range services { log.Printf("Service: %s (ID: %d) at %s", svc.Name, svc.ID, svc.Endpoint) } } ``` -------------------------------- ### Retrieve Services by Name Source: https://github.com/bk1031/rincon/blob/main/_autodocs/api-reference/service.md Fetches all instances of a service based on its name, performing a case-insensitive search. Useful for finding all running instances of a particular application. ```Go instances := service.GetServicesByName("my_service") log.Printf("Found %d instances of my_service", len(instances)) for _, inst := range instances { log.Printf(" Instance %d: %s", inst.ID, inst.Endpoint) } ``` -------------------------------- ### Configure Rincon in Docker Compose Source: https://github.com/bk1031/rincon/blob/main/README.md Integrates Rincon into an existing Docker Compose setup, configuring SQL storage and database connection details. ```yaml rincon: image: bk1031/rincon:latest restart: unless-stopped environment: PORT: "10311" STORAGE_MODE: "sql" DB_DRIVER: "postgres" DB_HOST: "localhost" DB_PORT: "5432" DB_NAME: "rincon" DB_USER: "postgres" DB_PASSWORD: "password" ports: - "10311:10311" ``` -------------------------------- ### InitializeRoutes Source: https://github.com/bk1031/rincon/blob/main/_autodocs/api-reference/http-handlers.md Registers all API endpoint handlers with the provided Gin router. This function maps HTTP methods and paths to their corresponding handler functions, specifying whether authentication is required for each route. ```APIDOC ## InitializeRoutes ### Description Registers all API endpoint handlers with the router. This function sets up the specific routes for interacting with services and routes, including their HTTP methods, paths, handlers, and authentication requirements. ### Method N/A (Go function) ### Endpoint N/A ### Registered Routes | Method | Path | Handler | Auth Required | |---|---|---|---| | GET | /rincon/ping | Ping | No | | GET | /rincon/services | GetAllServices | No | | GET | /rincon/services/:name | GetService | No | | DELETE | /rincon/services/:name | RemoveService | Yes | | GET | /rincon/services/:name/routes | GetRoutesForService | No | | POST | /rincon/services | CreateService | Yes | | GET | /rincon/routes | GetRoute | No | | POST | /rincon/routes | CreateRoute | Yes | | GET | /rincon/match | MatchRoute | No | ### Example Usage ```go router := api.SetupRouter() api.InitializeRoutes(router) ``` ``` -------------------------------- ### Register Route with Missing Leading Slash Source: https://github.com/bk1031/rincon/blob/main/_autodocs/errors.md Illustrates a failed attempt to register a route that does not start with a slash, showing the expected error response. ```bash # This will fail: curl -X POST http://localhost:10311/rincon/routes \ -H 'Content-Type: application/json' \ -H 'Authorization: Basic YWRtaW46YWRtaW4=' \ -d '{ "route": "users", # ❌ Missing leading slash "method": "GET", "service_name": "user_service" }' # Response: { "message": "route must start with a slash" } ``` -------------------------------- ### Load Balance Service Instance Source: https://github.com/bk1031/rincon/blob/main/_autodocs/api-reference/balancer.md Selects a service instance from available instances using a specified balancing strategy. Currently, only 'random' is supported. Use when you need to distribute requests across multiple instances of a service. ```Go func LoadBalance(serviceName string, balancer string) model.Service ``` ```Go instance := service.LoadBalance("user_service", "random") if instance.ID == 0 { log.Println("No instances available for user_service") } else { log.Printf("Selected instance %d at %s", instance.ID, instance.Endpoint) } ``` -------------------------------- ### GET /rincon/match Source: https://github.com/bk1031/rincon/blob/main/_autodocs/endpoints.md Matches an incoming request to a registered service based on the provided route and method. This endpoint is crucial for request routing and load balancing. ```APIDOC ## GET /rincon/match ### Description Match an incoming request to a service using registered routes. This endpoint determines which service instance should handle a given request based on the defined routing rules. ### Method GET ### Endpoint /rincon/match ### Parameters #### Query Parameters - **route** (string) - Yes - Request path without leading slash (e.g., "users/123") - **method** (string) - Yes - HTTP method (GET, POST, etc.) ### Response #### Success Response (200 OK) Returns a randomly selected Service instance that matches the route. | Field | Type | Description | |-------|------|-------------| | id | integer | Service instance ID | | name | string | Service name | | version | string | Service version | | endpoint | string | Service endpoint URL to forward request to | | health_check | string | Health check endpoint | | updated_at | string | ISO 8601 timestamp | | created_at | string | ISO 8601 timestamp | #### Response Example ```json { "id": 123456, "name": "user_service", "version": "1.0.0", "endpoint": "http://localhost:8080", "health_check": "http://localhost:8080/health", "updated_at": "2025-03-22T00:07:40.703258671-07:00", "created_at": "2025-03-22T00:07:40.703258754-07:00" } ``` #### Error Response (400 Bad Request) If route or method is missing. ```json { "message": "Route query is required" } ``` #### Error Response (404 Not Found) If no matching route is registered. ```json { "message": "No route [GET] /users/fake found" } ``` ``` -------------------------------- ### Get All Routes for a Specific Service Source: https://github.com/bk1031/rincon/blob/main/_autodocs/endpoints.md Retrieve all registered routes associated with a given service name. This is useful for inspecting the routing configuration for a particular service. ```bash curl 'http://localhost:10311/rincon/services/user_service/routes' ``` -------------------------------- ### Request Handling Flow Source: https://github.com/bk1031/rincon/blob/main/_autodocs/MODULES.md Details the steps involved in processing an incoming HTTP request, from authentication to database access and response. ```go HTTP Request ↓ api.AuthMiddleware() [Validate credentials for POST/PUT/DELETE] ↓ api.Router Handler (e.g., MatchRoute) ↓ service.* Function (e.g., MatchRoute) ↓ database.* Access (Get/Create/Update/Delete) ↓ database.Local or database.DB [Execute against storage] ↓ Return Response to Client ``` -------------------------------- ### Get Route Graph Source: https://github.com/bk1031/rincon/blob/main/_autodocs/api-reference/route.md Builds and returns an internal directed acyclic graph representing all registered routes. This graph is used for efficient route matching. ```go func GetRouteGraph() map[string][]model.RouteNode ``` -------------------------------- ### Route Stacking: Combining Methods Source: https://github.com/bk1031/rincon/blob/main/README.md Shows how Rincon stacks routes with the same path and service name by combining their HTTP methods. ```c New York: /users [GET] New York: /users [POST] --- New York: /users [GET,POST] ``` -------------------------------- ### Create a New Service Source: https://github.com/bk1031/rincon/blob/main/_autodocs/api-reference/service.md Use this function to register a new service or update an existing one. Ensure the service object includes name, version, endpoint, and health_check fields. Validation rules apply to these fields. ```go func CreateService(service model.Service) (model.Service, error) ``` ```go newService := model.Service{ Name: "My API Server", Version: "1.0.0", Endpoint: "http://localhost:8080", HealthCheck: "http://localhost:8080/health", } created, err := service.CreateService(newService) if err != nil { log.Fatalf("Failed to create service: %v", err) } log.Printf("Service registered with ID: %d", created.ID) ``` -------------------------------- ### Add New API Endpoint Source: https://github.com/bk1031/rincon/blob/main/_autodocs/MODULES.md Explains the process for adding a new API endpoint, including creating a handler, registering the route, and implementing service logic. ```go Create handler in `api/` package Register route in `api.InitializeRoutes()` Add service logic as needed Document in endpoints.md ``` -------------------------------- ### InitializeHeartbeat Source: https://github.com/bk1031/rincon/blob/main/_autodocs/api-reference/heartbeat.md Initializes the heartbeat scheduler and starts the appropriate heartbeat routine based on configuration. It reads HEARTBEAT_TYPE and HEARTBEAT_INTERVAL to determine the mode and frequency of heartbeats. ```APIDOC ## InitializeHeartbeat ### Description Initializes the heartbeat scheduler and starts the appropriate heartbeat routine based on configuration. It reads HEARTBEAT_TYPE and HEARTBEAT_INTERVAL to determine the mode and frequency of heartbeats. ### Go Function Signature ```go func InitializeHeartbeat() ``` ### Behavior 1. Reads the HEARTBEAT_TYPE configuration (defaults to "server") 2. Reads the HEARTBEAT_INTERVAL configuration (defaults to 10 seconds) 3. Creates a scheduled job that runs every HEARTBEAT_INTERVAL seconds 4. If HEARTBEAT_TYPE="server", starts ServerHeartbeat job 5. If HEARTBEAT_TYPE="client", starts ClientHeartbeat job 6. Returns the job ID (logged for debugging) ### Configuration | Variable | Type | Default | Description | |----------|------|---------|-------------| | HEARTBEAT_TYPE | string | "server" | Either "server" or "client" | | HEARTBEAT_INTERVAL | string | "10" | Interval in seconds | | HEARTBEAT_RETRY_COUNT | string | "3" | Retry attempts (server mode only) | | HEARTBEAT_RETRY_BACKOFF | string | "5000" | Backoff in milliseconds (server mode only) | ### Example Usage ```go // Called during Rincon startup service.InitializeHeartbeat() log.Println("Heartbeat scheduler started") ``` ``` -------------------------------- ### List All Registered Services Source: https://github.com/bk1031/rincon/blob/main/_autodocs/endpoints.md Retrieve a list of all registered service instances. Each service object includes its ID, name, version, endpoint, health check URL, and timestamps. ```json [ { "id": 941815, "name": "rincon", "version": "2.2.0", "endpoint": "http://localhost:10311", "health_check": "http://localhost:10311/rincon/ping", "updated_at": "2025-03-22T00:07:40.703258671-07:00", "created_at": "2025-03-22T00:07:40.703258754-07:00" } ] ``` ```bash curl http://localhost:10311/rincon/services ``` -------------------------------- ### Register or Update Service Source: https://github.com/bk1031/rincon/blob/main/_autodocs/endpoints.md Use this to register a new service or update an existing one. Ensure all required fields are present in the JSON request body. The service name is normalized. ```bash curl -X POST http://localhost:10311/rincon/services \ -H 'Content-Type: application/json' \ -H 'Authorization: Basic YWRtaW46YWRtaW4=' \ -d '{ "name": "User Service", "version": "1.0.0", "endpoint": "http://localhost:8080", "health_check": "http://localhost:8080/health" }' ``` -------------------------------- ### Validate Route Method String Source: https://github.com/bk1031/rincon/blob/main/_autodocs/types.md Checks if a route's method string contains only valid HTTP methods. Example demonstrates usage with a Route object. ```go func (r *Route) IsMethodValid() bool { // ... implementation details ... } ``` ```go route := &Route{Method: "GET,POST"} if route.IsMethodValid() { log.Println("Valid methods") } else { log.Println("Invalid methods") } ``` -------------------------------- ### Initialize Heartbeat Scheduler Source: https://github.com/bk1031/rincon/blob/main/_autodocs/api-reference/heartbeat.md Initializes the heartbeat scheduler based on configuration. Call this during Rincon startup. ```go func InitializeHeartbeat() ``` ```go // Called during Rincon startup service.InitializeHeartbeat() log.Println("Heartbeat scheduler started") ``` -------------------------------- ### Get Unique Service Name Count Source: https://github.com/bk1031/rincon/blob/main/_autodocs/api-reference/service.md Returns the count of distinct service names, ignoring multiple instances of the same service. Useful for understanding the diversity of services. ```Go unique := service.GetNumUniqueServices() log.Printf("Unique services: %d", unique) ``` -------------------------------- ### GET /rincon/services/:name Source: https://github.com/bk1031/rincon/blob/main/_autodocs/endpoints.md Retrieves a specific service by its ID or name. Returns a single service object if an ID is provided, or an array of service objects if a name is provided. ```APIDOC ## GET /rincon/services/:name ### Description Retrieve service by ID or name. ### Method GET ### Endpoint /rincon/services/{name} ### Parameters #### Path Parameters - **name** (string or integer) - Required - Service ID (integer) or service name (string) ### Response (200 OK) If ID is provided: Single Service object If name is provided: Array of Service objects (all instances) ### Response Example By ID: { "id": 941815, "name": "rincon", "version": "2.2.0", "endpoint": "http://localhost:10311", "health_check": "http://localhost:10311/rincon/ping", "updated_at": "2025-03-22T00:07:40.703258671-07:00", "created_at": "2025-03-22T00:07:40.703258754-07:00" } By name: [ { "id": 123456, "name": "user_service", "version": "1.0.0", "endpoint": "http://localhost:8080", "health_check": "http://localhost:8080/health", "updated_at": "2025-03-22T00:07:40.703258671-07:00", "created_at": "2025-03-22T00:07:40.703258754-07:00" } ] ### Response (404 Not Found) If ID doesn't exist ``` -------------------------------- ### Register a Route for a Service Source: https://github.com/bk1031/rincon/blob/main/README.md Registers a route '/service' for 'Service A' that accepts any HTTP method. ```bash curl -X "POST" "http://localhost:10311/rincon/routes" \ -H 'Content-Type: application/json; charset=utf-8' \ -u 'admin:admin' \ -d $'{ "route": "/service", "service_name": "Service A", "method": "*" }' ```