### Install Candi CLI from Source Source: https://github.com/golangid/candi/blob/master/README.md Install the Candi CLI by building it from source using `go install`. This ensures you have the latest version directly from the repository. ```bash $ go install github.com/golangid/candi/cmd/candi@latest $ candi ``` -------------------------------- ### Complete Tracer Usage Example Source: https://github.com/golangid/candi/blob/master/_autodocs/api-reference/tracer.md Demonstrates the complete lifecycle of setting up and using the tracer, from initialization to creating root and child spans with tags and logs. Use this for a full integration example. ```go package main import ( "context" "github.com/golangid/candi/tracer" ) func main() { // Initialize tracer platform jaegerTracer := initJaeger() tracer.SetTracerPlatformType(jaegerTracer) defer jaegerTracer.Disconnect(context.Background()) // Root span headers := extractHeaders(request) trace, ctx := tracer.StartTraceFromHeader(context.Background(), "UserAPI.GetUser", headers) defer trace.Finish() // Child spans getUser(ctx) } func getUser(ctx context.Context) { trace, ctx := tracer.StartTraceWithContext(ctx, "GetUser.Query") defer trace.Finish() trace.SetTag("user_id", 123) user, err := db.GetUser(ctx, 123) if err != nil { trace.SetError(err) return } trace.Log("user_name", user.Name) } ``` -------------------------------- ### Complete .env File Example Source: https://github.com/golangid/candi/blob/master/_autodocs/configuration.md A comprehensive example of a .env file for a Candi microservice, covering application, server, database, messaging, tracing, and CORS settings. ```dotenv # Application ENVIRONMENT=development BUILD_NUMBER=v1.0.0 SERVICE_NAME=user-service LOAD_CONFIG_TIMEOUT=30s DEBUG_MODE=true MAX_GOROUTINES=50 # Servers HTTP_PORT=8080 GRPC_PORT=9090 USE_REST=true USE_GRAPHQL=true USE_GRPC=true USE_SHARED_LISTENER=false HTTP_ROOT_PATH=/api/v1 BASIC_AUTH_USERNAME=admin BASIC_AUTH_PASS=securepassword # Workers USE_KAFKA_CONSUMER=true USE_CRON_SCHEDULER=true USE_TASK_QUEUE_WORKER=true TASK_QUEUE_DASHBOARD_PORT=8081 # Database DB_SQL_WRITE_DSN=postgres://user:pass@localhost:5432/mydb DB_SQL_READ_DSN=postgres://user:pass@localhost:5432/mydb DB_REDIS_READ_DSN=redis://localhost:6379/0 DB_REDIS_WRITE_DSN=redis://localhost:6379/0 # Kafka KAFKA_BROKERS=localhost:9092 KAFKA_CLIENT_ID=user-service KAFKA_CONSUMER_GROUP=user-service-group # Tracing OTEL_TRACING_HOST=localhost:4317 # CORS CORS_ALLOW_ORIGINS=http://localhost:3000,http://localhost:3001 CORS_ALLOW_METHODS=GET,POST,PUT,DELETE,OPTIONS CORS_ALLOW_HEADERS=Content-Type,Authorization CORS_ALLOW_CREDENTIAL=true ``` -------------------------------- ### Install Candi CLI for Linux Source: https://github.com/golangid/candi/blob/master/README.md Download and install the Candi CLI for Linux systems. Ensure the binary is executable and moved to a directory in your system's PATH. ```bash $ wget -O candi https://storage.googleapis.com/agungdp/bin/candi/candi-linux && chmod +x candi && sudo mv candi /usr/local/bin $ candi ``` -------------------------------- ### Development Configuration Example Source: https://github.com/golangid/candi/blob/master/_autodocs/configuration.md Sets up configuration variables for a development environment, enabling debug mode and specifying development-specific settings. ```bash DEBUG_MODE=true ENVIRONMENT=development LOAD_CONFIG_TIMEOUT=30s GRAPHQL_DISABLE_INTROSPECTION=false ``` -------------------------------- ### Integration Example: User Creation Handler Source: https://github.com/golangid/candi/blob/master/_autodocs/api-reference/wrapper.md An example of an HTTP handler that uses the wrapper to send standardized responses for request validation errors, internal server errors, and successful user creation. ```go package main import ( "net/http" "github.com/golangid/candi/wrapper" "github.com/golangid/candi/candishared" ) func handleCreateUser(w http.ResponseWriter, r *http.Request) { // Validate request if err := validateRequest(r); err != nil { resp := wrapper.NewHTTPResponse(400, "Invalid request", err) resp.JSON(w) return } // Create user user, err := createUser(r.Context()) if err != nil { resp := wrapper.NewHTTPResponse(500, "Failed to create user", err) resp.JSON(w) return } // Success resp := wrapper.NewHTTPResponse(201, "User created", user) resp.JSON(w) } ``` -------------------------------- ### Install Candi CLI for macOS Source: https://github.com/golangid/candi/blob/master/README.md Download and install the Candi CLI for macOS. Ensure the binary is executable and moved to a directory in your system's PATH. ```bash $ wget -O candi https://storage.googleapis.com/agungdp/bin/candi/candi-osx && chmod +x candi && mv candi /usr/local/bin $ candi ``` -------------------------------- ### Production Configuration Example Source: https://github.com/golangid/candi/blob/master/_autodocs/configuration.md Configures settings for a production environment, disabling debug mode and optimizing for performance and stability. ```bash DEBUG_MODE=false ENVIRONMENT=production LOAD_CONFIG_TIMEOUT=10s GRAPHQL_DISABLE_INTROSPECTION=true MAX_GOROUTINES=200 ``` -------------------------------- ### Example Configuration Initialization and Dependency Loading Source: https://github.com/golangid/candi/blob/master/_autodocs/api-reference/config.md Demonstrates the typical flow for initializing the configuration, deferring its exit, and loading dependencies with a context-aware timeout. Dependencies are automatically closed on exit. ```go func main() { // Initialize config cfg := config.Init("user-service") defer cfg.Exit() // Load dependencies with timeout cfg.LoadFunc(func(ctx context.Context) []interfaces.Closer { sqlDB := initSQL(ctx) cache := initRedis(ctx) kafkaBroker := broker.NewKafkaBroker() return []interfaces.Closer{sqlDB, cache, kafkaBroker} }) // Application runs... // On exit, all dependencies are gracefully closed } ``` -------------------------------- ### Zap Logger Initialization and Usage Example Source: https://github.com/golangid/candi/blob/master/_autodocs/api-reference/logger.md Demonstrates how to initialize the Zap logger with multiple writers and a custom masker, and how to log messages at different levels. ```go package main import ( "os" "github.com/golangid/candi/logger" "go.uber.org/zap/zapcore" ) func init() { // Initialize logger with multiple outputs logFile, _ := os.Create("logs/app.log") logger.InitZap( logger.SetMultiWriter(os.Stdout, logFile), ) // Set masker for sensitive data logger.SetMaskLog(MyPasswordMasker{}) } func main() { defer logger.LogWithDefer("Starting application... ")() logger.LogI("Application initialized") logger.Log(zapcore.InfoLevel, "Server ready", "main", "startup") } ``` -------------------------------- ### Example Usage of NewMeta Source: https://github.com/golangid/candi/blob/master/_autodocs/api-reference/shared.md Demonstrates creating pagination metadata with specific page, limit, and total records. ```go meta := candishared.NewMeta(1, 10, 150) // Page: 1, Limit: 10, TotalRecords: 150, TotalPages: 15 ``` -------------------------------- ### Masker Interface and TokenMasker Example Source: https://github.com/golangid/candi/blob/master/_autodocs/api-reference/logger.md Defines an interface for masking sensitive data in logs and provides an example implementation for masking JWT tokens. ```go type Masker interface { Mask(text string) string } ``` ```go type TokenMasker struct{} func (t TokenMasker) Mask(text string) string { // Mask JWT tokens if strings.HasPrefix(text, "eyJ") { return "eyJ***" } return text } ``` -------------------------------- ### Example Usage of ToFilter Source: https://github.com/golangid/candi/blob/master/_autodocs/api-reference/shared.md Demonstrates converting a NullableFilter to a Filter, showing default value application. ```go nullFilter := candishared.NullableFilter{Page: candihelper.ToIntPtr(2)} filter := nullFilter.ToFilter() // Page: 2, Limit: 10 ``` -------------------------------- ### Example Usage of CalculateOffset Source: https://github.com/golangid/candi/blob/master/_autodocs/api-reference/shared.md Shows how to calculate the offset for database queries using the Filter struct. ```go filter := candishared.Filter{Page: 2, Limit: 10} offset := filter.CalculateOffset() // 10 ``` -------------------------------- ### Example User Schema Source: https://github.com/golangid/candi/blob/master/_autodocs/api-reference/validator.md An example JSON schema defining the structure and constraints for a user object, including properties like id, name, email, and age, with specific validation rules. ```json { "$schema": "http://json-schema.org/draft-07/schema#", "type": "object", "properties": { "id": {"type": "integer"}, "name": { "type": "string", "minLength": 3, "maxLength": 100 }, "email": { "type": "string", "format": "email" }, "age": { "type": "integer", "minimum": 18 } }, "required": ["name", "email"] } ``` -------------------------------- ### Create New Service with Candi CLI Source: https://github.com/golangid/candi/blob/master/README.md Initialize a new service project using the Candi CLI. This command starts the project generation process. ```bash $ candi ``` -------------------------------- ### Example Usage of Candi Helper Functions Source: https://github.com/golangid/candi/blob/master/_autodocs/api-reference/helper.md Demonstrates the usage of various candihelper functions including environment parsing, safe pointer conversions, time zone conversion, and string slice checking. ```go package main import ( "time" "github.com/golangid/candi/candihelper" ) type AppConfig struct { ServiceName string `env:"SERVICE_NAME"` HTTPPort int `env:"HTTP_PORT" optional:"true"` DatabaseURL string `env:"DATABASE_URL"` Timeout time.Duration `env:"TIMEOUT" optional:"true"` AllowedRoles []string `env:"ALLOWED_ROLES" separator:","` } func main() { cfg := &AppConfig{} candihelper.MustParseEnv(cfg) // Safe pointer conversion name := candihelper.ToStringPtr(cfg.ServiceName) port := candihelper.ToIntPtr(cfg.HTTPPort) // Time zone conversion now := candihelper.ToAsiaJakartaTime(time.Now()) // String utilities allowed := []string{"admin", "user"} if candihelper.StringInSlice("admin", allowed) { println("Admin access granted") } } ``` -------------------------------- ### Handle Configuration Loading Timeout Source: https://github.com/golangid/candi/blob/master/_autodocs/errors.md This example shows how to use context timeouts within a LoadFunc to detect and handle scenarios where loading dependencies takes longer than the configured LOAD_CONFIG_TIMEOUT. ```Go cfg := config.Init("service") cfg.LoadFunc(func(ctx context.Context) []interfaces.Closer { // Use context timeout to detect timeouts select { case <-ctx.Done(): return nil // Timeout occurred default: // Load dependencies } }) ``` -------------------------------- ### Environment Variable Priority Example Source: https://github.com/golangid/candi/blob/master/_autodocs/configuration.md Demonstrates the order of precedence for configuration values, showing how environment variables override .env files and code defaults. ```bash # ~/.bashrc or system env export HTTP_PORT=8888 # .env file HTTP_PORT=8080 # Code default DefaultHTTPPort = 8080 # Result: HTTP_PORT = 8888 (system env wins) ``` -------------------------------- ### Example Usage of NewMultiError Source: https://github.com/golangid/candi/blob/master/_autodocs/api-reference/shared.md Demonstrates creating and appending errors to a MultiError instance, and checking for errors. ```go mErr := candishared.NewMultiError() mErr.Append("email", fmt.Errorf("invalid format")) mErr.Append("age", fmt.Errorf("must be positive")) if mErr.HasError() { log.Fatal(mErr.Error()) } ``` -------------------------------- ### Initialize Candi Configuration Programmatically Source: https://github.com/golangid/candi/blob/master/_autodocs/configuration.md Programmatically initialize the Candi configuration with a service name and custom options like log size. Ensures proper setup and deferred cleanup. ```go package main import ( "github.com/golangid/candi/config" ) func main() { // Initialize config with custom options cfg := config.Init("my-service", config.WithLogSize(200000), ) defer cfg.Exit() // Access environment env := config.BaseEnv() println(env.HTTPPort) println(env.ServiceName) } ``` -------------------------------- ### Example Usage of Result Struct Source: https://github.com/golangid/candi/blob/master/_autodocs/api-reference/shared.md Demonstrates how to use the Result struct to return data and potential errors from a function. ```go func getUser(id int) candishared.Result { user, err := db.FindUser(id) return candishared.Result{Data: user, Error: err} } ``` -------------------------------- ### Publish RabbitMQ Message in Usecase Source: https://github.com/golangid/candi/blob/master/broker/README.md Example of publishing a message using the RabbitMQ publisher in a usecase. Supports setting a delay for message consumption. ```go package usecase import ( "context" "github.com/golangid/candi/broker" "github.com/golangid/candi/candishared" "github.com/golangid/candi/codebase/factory/dependency" "github.com/golangid/candi/codebase/factory/types" "github.com/golangid/candi/codebase/interfaces" ) type usecaseImpl struct { rustingrabbitmqPub interfaces.Publisher } func NewUsecase(deps dependency.Dependency) Usecase { return &usecaseImpl{ rustingrabbitmqPub: deps.GetBroker(types.RabbitMQ).GetPublisher(), } } func (uc *usecaseImpl) UsecaseToPublishMessage(ctx context.Context) error { err := uc.rabbitmqPub.PublishMessage(ctx, &candishared.PublisherArgument{ Topic: "example-topic", Data: "hello world" Header: map[string]any{ broker.RabbitMQDelayHeader: 5000, // if you want set delay consume your message by active consumer for 5 seconds }, }) return err } ``` -------------------------------- ### Configure Middleware with Token Validator Source: https://github.com/golangid/candi/blob/master/_autodocs/errors.md This example shows how to set a TokenValidator when creating middleware. It also highlights the error message 'Missing token validator' that occurs if no validator is configured. ```Go mw := middleware.NewMiddlewareWithOption( middleware.SetTokenValidator(myValidator), ) ``` -------------------------------- ### Example Usage of SliceResult Struct Source: https://github.com/golangid/candi/blob/master/_autodocs/api-reference/shared.md Shows how to use SliceResult for paginated queries, including creating metadata. ```go func listUsers(page, limit int) candishared.SliceResult { users, total, err := db.ListUsers(page, limit) meta := candishared.NewMeta(page, limit, total) return candishared.SliceResult{Data: users, Meta: meta, Error: err} } ``` -------------------------------- ### Register Task Queue Handler in Module Source: https://github.com/golangid/candi/blob/master/codebase/app/task_queue_worker/README.md Shows how to register the TaskQueueHandler within a module's dependency injection setup. ```go package examplemodule import ( "example.service/internal/modules/examplemodule/delivery/workerhandler" "github.com/golangid/candi/codebase/factory/dependency" "github.com/golangid/candi/codebase/factory/types" "github.com/golangid/candi/codebase/interfaces" ) type Module struct { // ...another delivery handler workerHandlers map[types.Worker]interfaces.WorkerHandler } func NewModules(deps dependency.Dependency) *Module { return &Module{ workerHandlers: map[types.Worker]interfaces.WorkerHandler{ // ...another worker handler // ... types.TaskQueue: workerhandler.NewTaskQueueHandler(), }, } } // ...another method ``` -------------------------------- ### Get Default Kafka Configuration Source: https://github.com/golangid/candi/blob/master/_autodocs/api-reference/broker.md Creates a default Kafka Sarama configuration with production-ready settings. Allows for additional custom configuration functions to be applied. ```go config := broker.GetDefaultKafkaConfig(func(cfg *sarama.Config) { cfg.Producer.Retry.Max = 20 }) ``` -------------------------------- ### Create and Mount Cron Job Handlers Source: https://github.com/golangid/candi/blob/master/codebase/app/cron_worker/README.md Define a CronHandler struct and mount cron job handlers using `CreateCronJobKey`. This example shows how to schedule jobs with both interval and specific time expressions. ```go package workerhandler import ( "context" "fmt" "time" "github.com/golangid/candi/candishared" cronworker "github.com/golangid/candi/codebase/app/cron_worker" "github.com/golangid/candi/codebase/factory/types" "github.com/golangid/candi/logger" "github.com/golangid/candi/tracer" ) // CronHandler struct type CronHandler struct { } // NewCronHandler constructor func NewCronHandler() *CronHandler { return &CronHandler{} } // MountHandlers return group map topic key to handler func func (h *CronHandler) MountHandlers(group *types.WorkerHandlerGroup) { group.Add(cronworker.CreateCronJobKey("push-notif", "message", "30s"), h.handleJob1) group.Add(cronworker.CreateCronJobKey("heavy-push-notif", "message", "22:43:07"), h.handleJob2) } func (h *CronHandler) handleJob1(eventContext *candishared.EventContext) error { trace := tracer.StartTrace(eventContext.Context(), "DeliveryCronWorker:HandleJob1") defer trace.Finish() logger.LogI("running...") return nil } func (h *CronHandler) handleJob2(eventContext *candishared.EventContext) error { trace := tracer.StartTrace(eventContext.Context(), "DeliveryCronWorker:HandleJob2") defer trace.Finish() fmt.Println("processing") time.Sleep(30 * time.Second) fmt.Println("done") return nil } ``` -------------------------------- ### Publish Kafka Message in Usecase Source: https://github.com/golangid/candi/blob/master/broker/README.md Example of publishing a message using the Kafka publisher in a usecase. Ensure Kafka consumer is enabled via environment variable if needed. ```go package usecase import ( "context" "github.com/golangid/candi/candishared" "github.com/golangid/candi/codebase/factory/dependency" "github.com/golangid/candi/codebase/factory/types" "github.com/golangid/candi/codebase/interfaces" ) type usecaseImpl struct { kafkaPub interfaces.Publisher } func NewUsecase(deps dependency.Dependency) Usecase { return &usecaseImpl{ kafkaPub: deps.GetBroker(types.Kafka).GetPublisher(), } } func (uc *usecaseImpl) UsecaseToPublishMessage(ctx context.Context) error { err := uc.kafkaPub.PublishMessage(ctx, &candishared.PublisherArgument{ Topic: "example-topic", Data: "hello world", }) return err } ``` -------------------------------- ### Get Fresh Context Source: https://github.com/golangid/candi/blob/master/_autodocs/api-reference/tracer.md Returns a fresh context, typically used internally by the tracer implementation. ```go func (t Tracer) NewContext() context.Context ``` -------------------------------- ### Full Validation Example in Go Source: https://github.com/golangid/candi/blob/master/_autodocs/api-reference/validator.md Demonstrates a complete validation process for a user creation request in Go. It includes JSON decoding, JSON schema validation using ValidateDocument, and struct validation using ValidateStruct. ```go package main import ( "encoding/json" "net/http" "github.com/golangid/candi/validator" ) type CreateUserRequest struct { Name string `json:"name" validate:"required,min=3" Email string `json:"email" validate:"required,email" } func createUserHandler(w http.ResponseWriter, r *http.Request) { var req CreateUserRequest if err := json.NewDecoder(r.Body).Decode(&req); err != nil { http.Error(w, "Invalid JSON", 400) return } v := validator.NewValidator() // JSON schema validation if err := v.ValidateDocument("create_user", req); err != nil { http.Error(w, err.Error(), 400) return } // Struct validation if err := v.ValidateStruct(req); err != nil { http.Error(w, err.Error(), 400) return } // Process valid request user := createUser(r.Context(), req) json.NewEncoder(w).Encode(user) } ``` -------------------------------- ### Get All Registered Brokers Source: https://github.com/golangid/candi/blob/master/_autodocs/api-reference/broker.md Retrieves a map of all brokers currently registered in the broker registry. ```go brokers := brokerRegistry.GetBrokers() for workerType, broker := range brokers { fmt.Println(workerType, broker.GetName()) } ``` -------------------------------- ### Register Redis Handler in Module Source: https://github.com/golangid/candi/blob/master/codebase/app/redis_worker/README.md Shows how to register the created Redis handler within a module's dependency injection setup. ```go package examplemodule import ( "example.service/internal/modules/examplemodule/delivery/workerhandler" "github.com/golangid/candi/codebase/factory/dependency" "github.com/golangid/candi/codebase/factory/types" "github.com/golangid/candi/codebase/interfaces" ) type Module struct { // ...another delivery handler workerHandlers map[types.Worker]interfaces.WorkerHandler } func NewModules(deps dependency.Dependency) *Module { return &Module{ workerHandlers: map[types.Worker]interfaces.WorkerHandler{ // ...another worker handler // ... types.RedisSubscriber: workerhandler.NewRedisHandler(), }, } } // ...another method ``` -------------------------------- ### Get Global Environment Configuration Source: https://github.com/golangid/candi/blob/master/_autodocs/api-reference/config.md Retrieves the singleton instance of the global environment configuration. This is the primary way to access loaded configuration values throughout the application. ```go env := config.BaseEnv() port := env.HTTPPort ``` -------------------------------- ### Candi CLI Flag Options Source: https://github.com/golangid/candi/blob/master/README.md Detailed list of Candi CLI flags for project generation and service running. Use these flags to customize your project setup and execution. ```text Usage of candi: -add-handler [project generator] add handler in delivery module in service -add-module [project generator] add module in service -init [project generator] init service -init-monorepo [project generator] init monorepo codebase -libraryname string [project generator] define library name (default "github.com/golangid/candi"), you can custom set to CANDI_CLI_PACKAGES global environment variable -monorepo-name string [project generator] set monorepo project name (default "monorepo") -output string [project generator] directory to write project to (default is service name) -packageprefix string [project generator] define package prefix -protooutputpkg string [project generator] define generated proto output target (if using grpc), with prefix is your go.mod -run [service runner] run selected service or all service in monorepo -scope string [project generator] set scope 1 for init service, 2 for add module(s), 3 for add delivery handler(s) in module, 4 for init monorepo codebase, 5 for run multiple service in monorepo -service string Describe service name (if run multiple services, separate by comma) -version print version -withgomod [project generator] generate go.mod or not (default true) ``` -------------------------------- ### Register RabbitMQ Handler in Module Source: https://github.com/golangid/candi/blob/master/codebase/app/rabbitmq_worker/README.md Shows how to register the created RabbitMQ handler within the module's dependency injection setup. This ensures the handler is available for consuming messages. ```go package examplemodule import ( "example.service/internal/modules/examplemodule/delivery/workerhandler" "github.com/golangid/candi/codebase/factory/dependency" "github.com/golangid/candi/codebase/factory/types" "github.com/golangid/candi/codebase/interfaces" ) type Module struct { // ...another delivery handler workerHandlers map[types.Worker]interfaces.WorkerHandler } func NewModules(deps dependency.Dependency) *Module { return &Module{ workerHandlers: map[types.Worker]interfaces.WorkerHandler{ // ...another worker handler // ... types.RabbitMQ: workerhandler.NewRabbitMQHandler(usecaseUOW.User(), deps.GetValidator()), }, } } // ...another method ``` -------------------------------- ### Register Kafka Handler in Module Source: https://github.com/golangid/candi/blob/master/codebase/app/kafka_worker/README.md Shows how to register the Kafka handler within a module's dependency injection setup. Ensure the Kafka worker type is correctly mapped to the handler instance. ```go package examplemodule import ( "example.service/internal/modules/examplemodule/delivery/workerhandler" "github.com/golangid/candi/codebase/factory/dependency" "github.com/golangid/candi/codebase/factory/types" "github.com/golangid/candi/codebase/interfaces" ) type Module struct { // ...another delivery handler workerHandlers map[types.Worker]interfaces.WorkerHandler } func NewModules(deps dependency.Dependency) *Module { return &Module{ workerHandlers: map[types.Worker]interfaces.WorkerHandler{ // ...another worker handler // ... types.Kafka: workerhandler.NewKafkaHandler(), }, } } // ...another method ``` -------------------------------- ### Build and Run Service with Make Source: https://github.com/golangid/candi/blob/master/README.md Build and run your service using the provided Makefile. Navigate to your service directory and execute the `make run` command. ```bash cd {{service_name}} $ make run ``` -------------------------------- ### HTTP Cache Middleware Source: https://github.com/golangid/candi/blob/master/_autodocs/api-reference/middleware.md HTTP response caching middleware for GET requests. It caches successful GET responses using a default TTL and requires Cache to be configured. ```go func (m *Middleware) HTTPCache(next http.Handler) http.Handler { // ... implementation details ... } ``` ```go mux.Use(mw.HTTPCache) ``` -------------------------------- ### Configure Kafka Brokers and Client Source: https://github.com/golangid/candi/blob/master/_autodocs/configuration.md Set up Kafka connection details including broker addresses, client ID, client version, and consumer group. ```bash export KAFKA_BROKERS="localhost:9092,localhost:9093" export KAFKA_CLIENT_ID="my-service" export KAFKA_CLIENT_VERSION="2.8.0" export KAFKA_CONSUMER_GROUP="my-service-group" ``` -------------------------------- ### Initialize Configuration Source: https://github.com/golangid/candi/blob/master/_autodocs/api-reference/config.md Initializes the application configuration with a service name and optional configuration functions. It loads .env files and sets up a shared listener if enabled. ```go cfg := config.Init("user-service", config.WithLogSize(100000)) ``` -------------------------------- ### Init Source: https://github.com/golangid/candi/blob/master/_autodocs/api-reference/config.md Initializes application configuration with a service name and optional configuration functions. It loads .env files and sets up a shared TCP listener if enabled. ```APIDOC ## Init ### Description Initializes application configuration with service name and options. ### Method `Init` ### Parameters #### Path Parameters - **serviceName** (string) - Yes - Service name (used for logging and identification) - **opts** (...OptionFunc) - No - Configuration option functions ### Returns - `*Config` - Config instance ### Side Effects - Loads .env file via godotenv - Sets up optional shared TCP listener if USE_SHARED_LISTENER is enabled ### Example ```go cfg := config.Init("user-service", config.WithLogSize(100000)) ``` ``` -------------------------------- ### Initialize Brokers Source: https://github.com/golangid/candi/blob/master/_autodocs/configuration.md Initializes Kafka and RabbitMQ brokers using their respective configuration options. Ensure broker hosts are correctly specified. ```go brokerRegistry := broker.InitBrokers( broker.NewKafkaBroker( broker.KafkaSetBrokerHost([]string{"kafka:9092"}), ), broker.NewRabbitMQBroker(), ) ``` -------------------------------- ### Get Source: https://github.com/golangid/candi/blob/master/_autodocs/api-reference/cache.md Retrieves a value from cache by key. ```APIDOC ## Get ### Description Retrieves a value from cache by key. ### Method `Get` ### Parameters #### Path Parameters - None #### Query Parameters - None #### Request Body - None ### Parameters - **ctx** (context.Context) - Required - Context for tracing and cancellation - **key** (string) - Required - Cache key ### Returns - `[]byte` - Cached value - `error` - Redis error or cache miss (redis.ErrNil) ### Example ```go data, err := cache.Get(ctx, "user:123") if err == redis.ErrNil { log.Println("Key not found") } else if err != nil { log.Fatal(err) } ``` ``` -------------------------------- ### HTTPCache Source: https://github.com/golangid/candi/blob/master/_autodocs/api-reference/middleware.md HTTP response caching middleware for GET requests. ```APIDOC ## HTTPCache ### Description HTTP response caching middleware for GET requests. Caches successful GET responses using defaultCacheAge for TTL. Requires Cache to be configured. ### Method HTTP Middleware (applied using `mux.Use`) ### Endpoint N/A (Middleware) ### Example ```go mux.Use(mw.HTTPCache) ``` ``` -------------------------------- ### Get Span Context Source: https://github.com/golangid/candi/blob/master/_autodocs/api-reference/tracer.md Returns the context associated with the current span. ```go func (t Tracer) Context() context.Context ``` ```go trace := tracer.StartTrace(ctx, "MyOperation") newCtx := trace.Context() ``` -------------------------------- ### Get Filter Limit Source: https://github.com/golangid/candi/blob/master/_autodocs/api-reference/shared.md Method to retrieve the items per page limit from the filter. ```go func (f *Filter) GetLimit() int ``` -------------------------------- ### Configure Middleware Options Source: https://github.com/golangid/candi/blob/master/_autodocs/configuration.md Set up middleware with custom options, including token validation, permission checking, caching, and user ID extraction. ```go mw := middleware.NewMiddlewareWithOption( middleware.SetTokenValidator(myTokenValidator), middleware.SetACLPermissionChecker(myACLChecker), middleware.SetCache(redisCache, 5*time.Minute), middleware.SetUserIDExtractor(func(claim *candishared.TokenClaim) string { return claim.Subject }), ) ``` -------------------------------- ### Get Filter Page Number Source: https://github.com/golangid/candi/blob/master/_autodocs/api-reference/shared.md Method to retrieve the current page number from the filter. ```go func (f *Filter) GetPage() int ``` -------------------------------- ### Create Kafka Broker with Custom Host Source: https://github.com/golangid/candi/blob/master/_autodocs/api-reference/broker.md Creates and initializes a Kafka broker, allowing custom broker host addresses to be specified. Uses environment variables for other configurations if not provided. ```go kafkaBroker := broker.NewKafkaBroker( broker.KafkaSetBrokerHost([]string{"localhost:9092"}), ) ``` -------------------------------- ### Get Kafka Publisher Instance Source: https://github.com/golangid/candi/blob/master/_autodocs/api-reference/broker.md Returns the publisher instance associated with the Kafka broker. ```go publisher := kafkaBroker.GetPublisher() ``` -------------------------------- ### Create Middleware with Options Source: https://github.com/golangid/candi/blob/master/_autodocs/api-reference/middleware.md Creates a middleware instance using configuration options. Defaults are applied for basic auth and user ID extraction if not explicitly set. ```go mw := middleware.NewMiddlewareWithOption( middleware.SetTokenValidator(myTokenValidator), middleware.SetACLPermissionChecker(myACLChecker), middleware.SetCache(redisCache, 1*time.Hour), ) ``` -------------------------------- ### Candi CLI Help and Options Source: https://github.com/golangid/candi/blob/master/README.md Display available flags and options for the Candi CLI. This is useful for understanding project generation and service running commands. ```bash $ candi --help ``` -------------------------------- ### Get Value from Cache Source: https://github.com/golangid/candi/blob/master/_autodocs/api-reference/cache.md Retrieves a value from the cache by its key. Handles cache misses (redis.ErrNil) and other Redis errors. ```go data, err := cache.Get(ctx, "user:123") if err == redis.ErrNil { log.Println("Key not found") } else if err != nil { log.Fatal(err) } ``` -------------------------------- ### Initialize Broker Registry Source: https://github.com/golangid/candi/blob/master/_autodocs/api-reference/broker.md Initializes the broker registry with one or more broker implementations. Panics if a broker with the same name is registered twice. ```go kafkaBroker := broker.NewKafkaBroker() rabbitBroker := broker.NewRabbitMQBroker() brokerRegistry := broker.InitBrokers(kafkaBroker, rabbitBroker) ``` -------------------------------- ### Configure SQL Database Connection (PostgreSQL) Source: https://github.com/golangid/candi/blob/master/_autodocs/configuration.md Set the DSN for writing and reading from a PostgreSQL database replica. ```bash # PostgreSQL export DB_SQL_WRITE_DSN="postgres://user:password@localhost:5432/dbname" export DB_SQL_READ_DSN="postgres://user:password@localhost:5432/dbname" ``` -------------------------------- ### GraphQLErrorResolver Interface Source: https://github.com/golangid/candi/blob/master/_autodocs/api-reference/shared.md An interface that defines the structure for GraphQL-compatible error resolvers, including methods to get the error string and its extensions. ```APIDOC ## GraphQLErrorResolver Interface ### Description GraphQL-compatible error resolver. ### Methods - **Error() string** - Returns the error message. - **Extensions() map[string]any** - Returns the error extensions. ``` -------------------------------- ### GraphQLErrorResolver Interface Definition Source: https://github.com/golangid/candi/blob/master/_autodocs/api-reference/shared.md Defines the interface for a GraphQL-compatible error resolver, including methods for getting the error string and extensions. ```go type GraphQLErrorResolver interface { Error() string Extensions() map[string]any } ``` -------------------------------- ### GetValueFromContext Source: https://github.com/golangid/candi/blob/master/_autodocs/api-reference/shared.md Gets a value from the context using a specified key. This is useful for retrieving arbitrary data stored within the request context. ```APIDOC ## GetValueFromContext ### Description Gets value from context by key. ### Method Signature ```go func GetValueFromContext(ctx context.Context, key ContextKey) any ``` ### Example ```go claim := candishared.GetValueFromContext(ctx, candishared.ContextKeyTokenClaim) ``` ``` -------------------------------- ### Configure HTTP Server Settings Source: https://github.com/golangid/candi/blob/master/_autodocs/configuration.md Set the root path for HTTP routes, disable GraphQL introspection for production, and configure basic authentication credentials. ```bash export HTTP_ROOT_PATH=/api/v1 export BASIC_AUTH_USERNAME=admin export BASIC_AUTH_PASS=secure_password export GRAPHQL_DISABLE_INTROSPECTION=true # Production ``` -------------------------------- ### GetTTL Source: https://github.com/golangid/candi/blob/master/_autodocs/api-reference/cache.md Gets the remaining time-to-live for a key in the Redis cache. It returns the duration until the key expires or a negative duration if the key has no expiry. ```APIDOC ## GetTTL ### Description Gets the remaining time-to-live for a key. ### Method ```go func (r *RedisCache) GetTTL(ctx context.Context, key string) (time.Duration, error) ``` ### Parameters #### Path Parameters - **ctx** (context.Context) - Required - Context for tracing - **key** (string) - Required - Cache key ### Returns - **time.Duration** - Remaining TTL, or negative duration if key has no expiry - **error** - Redis error or nil ### Example ```go ttl, err := cache.GetTTL(ctx, "user:123") if err != nil { log.Fatal(err) } if ttl > 0 { fmt.Printf("Expires in %v\n", ttl) } ``` ``` -------------------------------- ### Configure SQL Database Connection (MySQL) Source: https://github.com/golangid/candi/blob/master/_autodocs/configuration.md Set the DSN for writing and reading from a MySQL database replica. ```bash # MySQL export DB_SQL_WRITE_DSN="user:password@tcp(localhost:3306)/dbname?parseTime=true" export DB_SQL_READ_DSN="user:password@tcp(localhost:3306)/dbname?parseTime=true" ``` -------------------------------- ### Create RabbitMQ Broker Source: https://github.com/golangid/candi/blob/master/_autodocs/api-reference/broker.md Creates and initializes a RabbitMQ broker. It uses environment variables for connection details and consumer group configuration. ```go func NewRabbitMQBroker(opts ...RabbitMQOptionFunc) *RabbitMQBroker ``` ```go rabbitBroker := broker.NewRabbitMQBroker() brokerRegistry := broker.InitBrokers(rabbitBroker) ``` -------------------------------- ### Create Redis Broker Source: https://github.com/golangid/candi/blob/master/_autodocs/api-reference/broker.md Creates and initializes a Redis broker for pub/sub messaging. It can be configured using RedisOptionFunc options. ```go func NewRedisBroker(opts ...RedisOptionFunc) *RedisBroker ``` ```go redisBroker := broker.NewRedisBroker() brokerRegistry := broker.InitBrokers(redisBroker) ``` -------------------------------- ### Get Value from Context Source: https://github.com/golangid/candi/blob/master/_autodocs/api-reference/shared.md Retrieves a value from the context using a specific key. Useful for accessing shared data like authentication tokens. ```Go func GetValueFromContext(ctx context.Context, key ContextKey) any ``` ```Go claim := candishared.GetValueFromContext(ctx, candishared.ContextKeyTokenClaim) ``` -------------------------------- ### Cache Interface Definition Source: https://github.com/golangid/candi/blob/master/_autodocs/api-reference/cache.md Defines the contract for cache implementations, outlining methods for Get, GetKeys, GetTTL, Set, Exists, Delete, and DoCommand. ```go type Cache interface { Get(ctx context.Context, key string) ([]byte, error) GetKeys(ctx context.Context, pattern string) ([]string, error) GetTTL(ctx context.Context, key string) (time.Duration, error) Set(ctx context.Context, key string, value any, expire time.Duration) error Exists(ctx context.Context, key string) (bool, error) Delete(ctx context.Context, key string) error DoCommand(ctx context.Context, isWrite bool, command string, args ...any) (any, error) } ``` -------------------------------- ### Get All Keys Matching Pattern Source: https://github.com/golangid/candi/blob/master/_autodocs/api-reference/cache.md Retrieves a list of all keys that match a given Redis pattern. Useful for cache inspection or batch operations. ```go keys, err := cache.GetKeys(ctx, "user:*") if err != nil { log.Fatal(err) } for _, key := range keys { fmt.Println(key) } ``` -------------------------------- ### Register Broker Safely Source: https://github.com/golangid/candi/blob/master/_autodocs/errors.md Demonstrates how to avoid panics caused by duplicate broker registrations by checking if a broker has already been registered before attempting to register it again. ```Go // Avoid re-registering same broker brokerRegistry.RegisterBroker(types.Kafka, newKafkaBroker) // Panics if already registered ``` -------------------------------- ### Register Cron Handler in Module Source: https://github.com/golangid/candi/blob/master/codebase/app/cron_worker/README.md Register the `CronHandler` within your module's constructor. This ensures the cron jobs are initialized and available when the application starts. ```go package examplemodule import ( "example.service/internal/modules/examplemodule/delivery/workerhandler" "github.com/golangid/candi/codebase/factory/dependency" "github.com/golangid/candi/codebase/factory/types" "github.com/golangid/candi/codebase/interfaces" ) type Module struct { // ...another delivery handler workerHandlers map[types.Worker]interfaces.WorkerHandler } func NewModules(deps dependency.Dependency) *Module { return &Module{ workerHandlers: map[types.Worker]interfaces.WorkerHandler{ // ...another worker handler // ... types.Scheduler: workerhandler.NewCronHandler(), }, } } // ...another method ``` -------------------------------- ### Set Application Environment Variables Source: https://github.com/golangid/candi/blob/master/_autodocs/configuration.md Configure application environment, build number, load timeouts, debug mode, and maximum goroutines. ```bash export ENVIRONMENT=production export BUILD_NUMBER=v1.2.3 export LOAD_CONFIG_TIMEOUT=30s export DEBUG_MODE=false export MAX_GOROUTINES=50 ``` -------------------------------- ### Register a New Broker Source: https://github.com/golangid/candi/blob/master/_autodocs/api-reference/broker.md Registers a new broker implementation with the registry after initialization. Panics if a broker with the same name already exists. ```go newBroker := broker.NewKafkaBroker() brokerRegistry.RegisterBroker(types.Kafka, newBroker) ``` -------------------------------- ### gRPC Basic Authentication Interceptor Source: https://github.com/golangid/candi/blob/master/_autodocs/api-reference/middleware.md gRPC basic authentication interceptor. This example shows how to integrate the GRPCBasicAuth method into a gRPC server's unary interceptors. ```go func (m *Middleware) GRPCBasicAuth(ctx context.Context) (context.Context, error) { // ... implementation details ... } ``` ```go unaryInterceptors := []grpc.UnaryServerInterceptor{ func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) { newCtx, err := mw.GRPCBasicAuth(ctx) if err != nil { return nil, err } return handler(newCtx, req) }, } ``` -------------------------------- ### Cache Interface Source: https://github.com/golangid/candi/blob/master/_autodocs/api-reference/shared.md Defines the contract for cache operations, including getting, setting, and deleting keys, as well as managing cache expiration and executing raw commands. ```APIDOC ## Cache Interface ### Description Interface for cache operations. ### Methods - **Get(ctx context.Context, key string) ([]byte, error)**: Retrieves a value from the cache by key. - **GetKeys(ctx context.Context, pattern string) ([]string, error)**: Retrieves a list of keys matching a pattern. - **GetTTL(ctx context.Context, key string) (time.Duration, error)**: Gets the time-to-live for a given key. - **Set(ctx context.Context, key string, value any, expire time.Duration) error**: Sets a key-value pair in the cache with an expiration time. - **Exists(ctx context.Context, key string) (bool, error)**: Checks if a key exists in the cache. - **Delete(ctx context.Context, key string) error**: Deletes a key from the cache. - **DoCommand(ctx context.Context, isWrite bool, command string, args ...any) (any, error)**: Executes a raw cache command. ``` -------------------------------- ### NewRabbitMQBroker Source: https://github.com/golangid/candi/blob/master/_autodocs/api-reference/broker.md Creates and initializes a RabbitMQ broker. ```APIDOC ## NewRabbitMQBroker ### Description Creates and initializes a RabbitMQ broker. ### Method Go Function ### Environment Variables Used: - `RABBITMQ_BROKER` - Connection URI - `RABBITMQ_CONSUMER_GROUP` - Consumer group name - `RABBITMQ_EXCHANGE_NAME` - Exchange name ### Example: ```go rabbitBroker := broker.NewRabbitMQBroker() brokerRegistry := broker.InitBrokers(rabbitBroker) ``` ### Signature ```go func NewRabbitMQBroker(opts ...RabbitMQOptionFunc) *RabbitMQBroker ``` ``` -------------------------------- ### GetOption Source: https://github.com/golangid/candi/blob/master/_autodocs/api-reference/config.md Returns the current configuration options, including the maximum log size. ```APIDOC ## GetOption ### Description Returns the configuration options. ### Method `GetOption` ### Returns - `*Option` - Option struct with MaxLogSize ### Example ```go options := cfg.GetOption() fmt.Println(options.MaxLogSize) ``` ``` -------------------------------- ### BaseEnv Source: https://github.com/golangid/candi/blob/master/_autodocs/api-reference/config.md Returns the global environment configuration singleton. This function provides access to the application's current environment settings. ```APIDOC ## BaseEnv ### Description Returns the global environment configuration singleton. ### Signature ```go func BaseEnv() Env ``` ### Example ```go env := config.BaseEnv() port := env.HTTPPort ``` ``` -------------------------------- ### Configure Custom Logger with Zap Source: https://github.com/golangid/candi/blob/master/_autodocs/configuration.md Set up a custom logger using Zap, enabling multi-writer output (stdout and file) and password masking. ```go package main import ( "os" "github.com/golangid/candi/logger" ) func init() { // Custom logger setup logFile, _ := os.Create("app.log") logger.InitZap( logger.SetMultiWriter(os.Stdout, logFile), ) // Set password masker logger.SetMaskLog(MyPasswordMasker{}) } ``` -------------------------------- ### Get Trace View URL Source: https://github.com/golangid/candi/blob/master/_autodocs/api-reference/tracer.md Use GetTraceURL to obtain the URL for viewing the current trace in a UI like Jaeger. Returns an empty string if the URL cannot be determined. ```go traceURL := tracer.GetTraceURL(ctx) if traceURL != "" { log.Printf("View trace: %s\n", traceURL) } ``` -------------------------------- ### StartTrace Source: https://github.com/golangid/candi/blob/master/_autodocs/api-reference/tracer.md Creates a child span from the parent context. Returns a Tracer interface for recording trace events. ```APIDOC ## StartTrace ### Description Creates a child span from parent context. ### Function Signature ```go func StartTrace(ctx context.Context, operationName string) Tracer ``` ### Parameters #### Path Parameters - **ctx** (context.Context) - Required - Parent context - **operationName** (string) - Required - Span operation name ### Returns - `Tracer` - Span tracer (or NoopTracer if disabled) ### Behavior - Returns NoopTracer if skipTracer context key is set - Extracts parent span from context - Creates child span in platform tracer ### Example ```go func processUser(ctx context.Context, userID string) { trace := tracer.StartTrace(ctx, "ProcessUser") defer trace.Finish() trace.SetTag("user_id", userID) // Process user } ``` ``` -------------------------------- ### NewMiddlewareWithOption Source: https://github.com/golangid/candi/blob/master/_autodocs/api-reference/middleware.md Creates a new Middleware instance with customizable options. It allows setting token validators, ACL checkers, cache implementations, and user ID extractors. Default behavior uses environment variables for basic auth and extracts user ID from the token's Subject field. ```APIDOC ## NewMiddlewareWithOption ### Description Creates middleware with full configuration options. ### Signature ```go func NewMiddlewareWithOption(opts ...OptionFunc) *Middleware ``` ### Parameters #### Options (`opts`) - `...OptionFunc`: Functions to configure the middleware. See Configuration Options below. ### Returns - `*Middleware`: A configured middleware instance. ### Default Behavior - Basic auth uses environment variables (BASIC_AUTH_USERNAME, BASIC_AUTH_PASS). - User ID is extracted from the token's Subject field. ### Example ```go mw := middleware.NewMiddlewareWithOption( middleware.SetTokenValidator(myTokenValidator), middleware.SetACLPermissionChecker(myACLChecker), middleware.SetCache(redisCache, 1*time.Hour), ) ``` ``` -------------------------------- ### NewKafkaBroker Source: https://github.com/golangid/candi/blob/master/_autodocs/api-reference/broker.md Creates and initializes a Kafka broker using the Sarama client. ```APIDOC ## NewKafkaBroker ### Description Creates and initializes a Kafka broker. ### Method `func NewKafkaBroker(opts ...KafkaOptionFunc) *KafkaBroker` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Parameters Table | Parameter | Type | Required | Default | Description | |-----------|------|----------|---------|-------------| | opts | ...KafkaOptionFunc | No | types.Kafka | Configuration option functions | ### Returns `*KafkaBroker` - Initialized Kafka broker ### Environment Variables Used: - `KAFKA_BROKERS` - Comma-separated broker addresses - `KAFKA_CLIENT_ID` - Client identifier - `KAFKA_CLIENT_VERSION` - Kafka version (default: "2.0.0") ### Panics If broker connection fails ### Example ```go kafkaBroker := broker.NewKafkaBroker( broker.KafkaSetBrokerHost([]string{"localhost:9092"}), ) ``` ``` -------------------------------- ### Register RabbitMQ Broker in Service Config Source: https://github.com/golangid/candi/blob/master/broker/README.md Modify your service's configs/configs.go to initialize the RabbitMQ broker. ```go package configs import ( "github.com/golangid/candi/broker" ... // LoadServiceConfigs load selected dependency configuration in this service func LoadServiceConfigs(baseCfg *config.Config) (deps dependency.Dependency) { ... brokerDeps := broker.InitBrokers( broker.NewRabbitMQBroker(), ) ... } ``` -------------------------------- ### Configure Server Ports Source: https://github.com/golangid/candi/blob/master/_autodocs/configuration.md Set the HTTP and gRPC ports for the server. These are conditionally required based on server type activation. ```bash export HTTP_PORT=8080 export GRPC_PORT=9090 ``` -------------------------------- ### Handle Broker Connection Failure Source: https://github.com/golangid/candi/blob/master/_autodocs/errors.md This pattern shows the expected error message format when a connection to a broker (Kafka or RabbitMQ) fails during initialization. ```Go [error_message]. Brokers: [broker_list] ``` -------------------------------- ### Register Kafka Broker in Service Config Source: https://github.com/golangid/candi/blob/master/broker/README.md Modify your service's configs/configs.go to initialize the Kafka broker. ```go package configs import ( "github.com/golangid/candi/broker" ... // LoadServiceConfigs load selected dependency configuration in this service func LoadServiceConfigs(baseCfg *config.Config) (deps dependency.Dependency) { ... brokerDeps := broker.InitBrokers( broker.NewKafkaBroker(), ) ... } ```