### Setup Multiple Services with Testcontainers Source: https://github.com/ankorstore/yokai-contrib/blob/main/_autodocs/api-reference/fxtestcontainer.md Illustrates how to set up and manage multiple Docker containers simultaneously for testing complex service dependencies. This example shows starting both a Redis and a PostgreSQL container, demonstrating how to defer their termination to ensure they are cleaned up after use. Use this pattern when your application relies on several external services. ```go func setupServices(ctx context.Context) error { // Start Redis redisConfig := &fxtestcontainer.ContainerConfig{ Image: "redis:latest", Port: "6379/tcp", } redis, err := fxtestcontainer.CreateGenericContainer(ctx, redisConfig) if err != nil { return err } defer redis.Terminate(ctx) // Start PostgreSQL pgConfig := &fxtestcontainer.ContainerConfig{ Image: "postgres:15", Port: "5432/tcp", Environment: map[string]string{ "POSTGRES_PASSWORD": "password", }, } postgres, err := fxtestcontainer.CreateGenericContainer(ctx, pgConfig) if err != nil { return err } defer postgres.Terminate(ctx) // Use both containers return nil } ``` -------------------------------- ### Start Google Cloud Pub/Sub Emulator Source: https://github.com/ankorstore/yokai-contrib/blob/main/_autodocs/configuration.md Instructions for starting the Pub/Sub emulator locally for development and testing. This involves installing the emulator, starting it, and setting the environment variable. ```bash # Install emulator gcloud components install pubsub-emulator # Start emulator (listens on port 8085 by default) gcloud beta emulators pubsub start --host-port=localhost:8085 # Set environment export PUBSUB_EMULATOR_HOST=localhost:8085 ``` -------------------------------- ### Install Fx Slack Module Source: https://github.com/ankorstore/yokai-contrib/blob/main/fxslack/README.md Install the fxhttpclient and fxslack modules using go get. ```shell go get github.com/ankorstore/yokai/fxhttpclient go get github.com/ankorstore/yokai-contrib/fxslack ``` -------------------------------- ### Install Yokai GCP Pub/Sub Module Source: https://github.com/ankorstore/yokai-contrib/blob/main/fxgcppubsub/README.md Install the fxgcppubsub module using go get. ```shell go get github.com/ankorstore/yokai-contrib/fxgcppubsub ``` -------------------------------- ### Install Yokai Test Container Module Source: https://github.com/ankorstore/yokai-contrib/blob/main/fxtestcontainer/README.md Install the module using go get. ```shell go get github.com/ankorstore/yokai-contrib/fxtestcontainer ``` -------------------------------- ### Install Fx Redis Module Source: https://github.com/ankorstore/yokai-contrib/blob/main/fxredis/README.md Install the fxredis module using go get. ```shell go get github.com/ankorstore/yokai-contrib/fxredis ``` -------------------------------- ### Example: Bootstrapping MySQL Server and Querying Database Source: https://github.com/ankorstore/yokai-contrib/blob/main/_autodocs/api-reference/fxgomysqlserver.md This example demonstrates how to bootstrap the MySQL server module and invoke a function to query the database. Ensure the necessary modules and dependencies are imported. ```go package main import ( "context" "database/sql" "github.com/ankorstore/yokai-contrib/fxgomysqlserver" "github.com/ankorstore/yokai/fxcore" _ "github.com/go-sql-driver/mysql" "go.uber.org/fx" ) func main() { app := fxcore.NewBootstrapper().WithOptions( fxgomysqlserver.FxGoMySQLServerModule, fx.Invoke(QueryDatabase), ).Bootstrap() } func QueryDatabase(srv *server.Server) error { db, err := sql.Open("mysql", "user:password@tcp(localhost:3306)/db") if err != nil { return err } defer db.Close() var result string return db.QueryRowContext(context.Background(), "SELECT 1").Scan(&result) } ``` -------------------------------- ### Install Fx Go MySQL Server Module Source: https://github.com/ankorstore/yokai-contrib/blob/main/fxgomysqlserver/README.md Install the fxgomysqlserver module using go get. ```shell go get github.com/ankorstore/yokai-contrib/fxgomysqlserver ``` -------------------------------- ### Yokai Contrib Module Initialization Example Source: https://github.com/ankorstore/yokai-contrib/blob/main/_autodocs/README.md Shows how to initialize and bootstrap a Yokai application using various contrib modules like fxelasticsearch, fxredis, and fxjsonapi. This example assumes the Yokai framework and Fx for dependency injection. ```go package main import ( "github.com/ankorstore/yokai-contrib/fxelasticsearch" "github.com/ankorstore/yokai-contrib/fxredis" "github.com/ankorstore/yokai-contrib/fxjsonapi" "github.com/ankorstore/yokai/fxcore" "go.uber.org/fx" ) func main() { app := fxcore.NewBootstrapper().WithOptions( fxelasticsearch.FxElasticsearchModule, fxredis.FxRedisModule, fxjsonapi.FxJSONAPIModule, fx.Invoke(runApplication), ).Bootstrap() } func runApplication( esClient *elasticsearch.Client, redisClient *redis.Client, processor fxjsonapi.Processor, ) error { // Your application code here return nil } ``` -------------------------------- ### Example ContainerConfig Initialization Source: https://github.com/ankorstore/yokai-contrib/blob/main/_autodocs/api-reference/fxtestcontainer.md Illustrates how to initialize a ContainerConfig struct with specific settings for a Redis container. ```go config := &ContainerConfig{ Name: "redis-test", Image: "redis:latest", Port: "6379/tcp", ExposedPorts: []string{"6379/tcp"}, Environment: map[string]string{ "REDIS_PASSWORD": "testpass", }, WaitingFor: wait.ForListeningPort("6379/tcp"), Cmd: []string{"redis-server", "--requirepass", "testpass"}, } ``` -------------------------------- ### Create and Start MySQL Server Source: https://github.com/ankorstore/yokai-contrib/blob/main/_autodocs/api-reference/fxgomysqlserver.md Use this function to create and start a MySQL server instance within your application. It handles configuration reading, server creation via a factory, background startup, and graceful shutdown registration. ```go func NewFxGoMySQLServer(p FxGoMySQLServerParam) (*server.Server, error) ``` -------------------------------- ### Install fxjsonapi Module Source: https://github.com/ankorstore/yokai-contrib/blob/main/fxjsonapi/README.md Install the fxjsonapi module using go get. This command fetches the package and adds it to your project's dependencies. ```shell go get github.com/ankorstore/yokai-contrib/fxjsonapi ``` -------------------------------- ### GCP Pub/Sub Test Server Example Source: https://github.com/ankorstore/yokai-contrib/blob/main/_autodocs/api-reference/fxgcppubsub.md Demonstrates setting up a test environment with a mock Pub/Sub server for integration testing. It shows how to publish and retrieve a message ID. ```go package handler_test import ( "context" "testing" "github.com/ankorstore/yokai-contrib/fxgcppubsub" "github.com/slack-go/slack" "go.uber.org/fx" "go.uber.org/fx/fxtest" ) func TestPublishSubscribe(t *testing.T) { t.Setenv("APP_ENV", "test") var publisher fxgcppubsub.Publisher var subscriber fxgcppubsub.Subscriber app := fxtest.New( t, fxgcppubsub.FxGcpPubSubModule, fx.Populate(&publisher, &subscriber), ) app.RequireStart() defer app.RequireStop() ctx := context.Background() // Publish message result, err := publisher.Publish(ctx, "test-topic", "hello") if err != nil { t.Fatalf("publish error: %v", err) } msgID, err := result.Get(ctx) if err != nil { t.Fatalf("publish result error: %v", err) } t.Logf("published message: %s", msgID) } ``` -------------------------------- ### Example Architecture: Event-Driven System Source: https://github.com/ankorstore/yokai-contrib/blob/main/_autodocs/api-reference/INDEX.md An example architecture for an event-driven system using GCP Pub/Sub for publishing/subscribing, Redis for temporary state, Slack for notifications, and Elasticsearch for logging. ```text fxgcppubsub (publisher/subscriber) + fxredis (temporary state) + fxslack (notifications) + fxelasticsearch (logging) ``` -------------------------------- ### Install Fx Elasticsearch Module Source: https://github.com/ankorstore/yokai-contrib/blob/main/fxelasticsearch/README.md Install the fxelasticsearch module using go get. This command fetches the module and adds it to your project's dependencies. ```shell go get github.com/ankorstore/yokai-contrib/fxelasticsearch ``` -------------------------------- ### Example Architecture: Microservice with Search Source: https://github.com/ankorstore/yokai-contrib/blob/main/_autodocs/api-reference/INDEX.md An example architecture for a microservice that includes HTTP server, JSON API protocol, Elasticsearch for search, and Redis for caching. ```text fxhttpserver (HTTP server) + fxjsonapi (JSON API protocol) + fxelasticsearch (search engine) + fxredis (caching) ``` -------------------------------- ### Example: Caching a Value with FxRedis Source: https://github.com/ankorstore/yokai-contrib/blob/main/_autodocs/api-reference/fxredis.md Demonstrates bootstrapping the FxRedisModule and using the injected Redis client to set a value. This example assumes a Redis DSN is configured. ```go package main import ( "context" "github.com/ankorstore/yokai-contrib/fxredis" "github.com/ankorstore/yokai/fxcore" "github.com/redis/go-redis/v9" "go.uber.org/fx" ) func main() { app := fxcore.NewBootstrapper().WithOptions( fxredis.FxRedisModule, fx.Invoke(CacheValue), ).Bootstrap() } func CacheValue(client *redis.Client) error { ctx := context.Background() return client.Set(ctx, "key", "value", 0).Err() } ``` -------------------------------- ### Run Test Application with Fx Go MySQL Server Source: https://github.com/ankorstore/yokai-contrib/blob/main/fxgomysqlserver/README.md Start the application in test mode, enabling the FxGoMySQLServerModule to provide an in-memory database for tests. This function is a helper for test setups. ```go // internal/bootstrap.go package internal import ( "testing" "github.com/ankorstore/yokai-contrib/fxgomysqlserver" ) // RunTest starts the application in test mode, with an optional list of [fx.Option]. func RunTest(tb testing.TB, options ...fx.Option) { b.Helper() // ... Bootstrapper.RunTestApp( b, // enable and start the server fxgomysqlserver.FxGoMySQLServerModule, // apply per test options fx.Options(options...), ) } ``` -------------------------------- ### Example Configuration for Yokai Contrib Modules Source: https://github.com/ankorstore/yokai-contrib/blob/main/_autodocs/README.md This YAML snippet shows a quick configuration example for various yokai-contrib modules, including Elasticsearch, Redis, Slack, JSON API, Google Cloud Pub/Sub, Go MySQL Server, and Testcontainers. ```yaml modules: elasticsearch: address: http://localhost:9200 redis: dsn: redis://localhost:6379/0 slack: auth_token: xoxb-token app_level_token: xapp-token jsonapi: log: enabled: true gcppubsub: project: id: my-project gomysqlserver: config: transport: memory database: testdb testcontainer: containers: postgres: image: postgres:15 port: "5432/tcp" ``` -------------------------------- ### Memory Transport Connection Example (Testing) Source: https://github.com/ankorstore/yokai-contrib/blob/main/_autodocs/api-reference/fxgomysqlserver.md Example of establishing a database connection using the memory transport, suitable for testing environments. This avoids external dependencies. ```go package main import ( "database/sql" _ "github.com/go-sql-driver/mysql" ) func main() { // Memory transport uses in-memory connection db, _ := sql.Open("mysql", "user:password@memory(bufconn)/db") defer db.Close() // Query database } ``` -------------------------------- ### NewFxGoMySQLServer Source: https://github.com/ankorstore/yokai-contrib/blob/main/_autodocs/api-reference/fxgomysqlserver.md Creates and starts a MySQL server instance. It handles configuration reading, server creation, background startup, and graceful shutdown registration. ```APIDOC ## NewFxGoMySQLServer ### Description Creates and starts a MySQL server instance. It reads configuration for logging and tracing, creates the server instance via a factory, starts the server in a background goroutine, registers a graceful shutdown hook, and logs the connection DSN on startup. ### Function Signature ```go func NewFxGoMySQLServer(p FxGoMySQLServerParam) (*server.Server, error) ``` ### Parameters #### Function Parameters - **p** (*FxGoMySQLServerParam*) - Required - DI parameters with Config, Factory, Logger, LifeCycle ### Returns - **`*server.Server`** - Running server instance - **`error`** - Server creation or startup error ### Configuration Configuration is managed via the `modules.gomysqlserver` section in configuration files. #### `modules.gomysqlserver.config` - **transport** (string) - Optional - Default: "tcp" - Connection protocol (tcp, memory) - **user** (string) - Optional - Default: "user" - Superuser name - **password** (string) - Optional - Default: "password" - Superuser password - **host** (string) - Optional - Default: "localhost" - TCP bind address - **port** (int) - Optional - Default: 3306 - TCP bind port - **database** (string) - Optional - Default: "db" - Database name #### `modules.gomysqlserver.log` - **enabled** (bool) - Optional - Default: false - Enable SQL execution logs #### `modules.gomysqlserver.trace` - **enabled** (bool) - Optional - Default: false - Enable OpenTelemetry tracing ### Example Usage ```go package main import ( "context" "database/sql" "github.com/ankorstore/yokai-contrib/fxgomysqlserver" "github.com/ankorstore/yokai/fxcore" _ "github.com/go-sql-driver/mysql" "go.uber.org/fx" ) func main() { app := fxcore.NewBootstrapper().WithOptions( fxgomysysqlserver.FxGoMySQLServerModule, fx.Invoke(QueryDatabase), ).Bootstrap() } func QueryDatabase(srv *server.Server) error { db, err := sql.Open("mysql", "user:password@tcp(localhost:3306)/db") if err != nil { return err } defer db.Close() var result string return db.QueryRowContext(context.Background(), "SELECT 1").Scan(&result) } ``` ``` -------------------------------- ### Example Usage of CreateGenericContainer Source: https://github.com/ankorstore/yokai-contrib/blob/main/_autodocs/api-reference/fxtestcontainer.md Demonstrates how to create and manage a PostgreSQL test container using CreateGenericContainer. ```go package main import ( "context" "github.com/ankorstore/yokai-contrib/fxtestcontainer" "github.com/testcontainers/testcontainers-go/wait" ) func main() { ctx := context.Background() config := &fxtestcontainer.ContainerConfig{ Image: "postgres:15", Port: "5432/tcp", Environment: map[string]string{ "POSTGRES_PASSWORD": "testpass", "POSTGRES_DB": "testdb", }, WaitingFor: wait.ForLog("database system is ready to accept connections"), } container, err := fxtestcontainer.CreateGenericContainer(ctx, config) if err != nil { panic(err) } defer container.Terminate(ctx) // Use container in tests } ``` -------------------------------- ### Example Architecture: Tested Application Source: https://github.com/ankorstore/yokai-contrib/blob/main/_autodocs/api-reference/INDEX.md An example architecture for a tested application that includes a main application component, fxtestcontainer for Docker containers, fxgomysqlserver for a test database, and Redis for a test cache. ```text fxapp (main application) + fxtestcontainer (Docker containers) + fxgomysqlserver (test database) + fxredis (test cache) ``` -------------------------------- ### TCP Transport Connection Example Source: https://github.com/ankorstore/yokai-contrib/blob/main/_autodocs/api-reference/fxgomysqlserver.md Example of establishing a database connection using the TCP transport. Ensure your configuration matches the host and port specified. ```go package main import ( "database/sql" _ "github.com/go-sql-driver/mysql" ) func main() { // Configuration shows host: localhost, port: 3306 db, _ := sql.Open("mysql", "user:password@tcp(localhost:3306)/db") defer db.Close() // Query database } ``` -------------------------------- ### Fx Redis Configuration Example Source: https://github.com/ankorstore/yokai-contrib/blob/main/fxredis/README.md Example YAML configuration for the Redis module, specifying the Data Source Name (DSN). ```yaml # ./configs/config.yaml app: name: app env: dev version: 0.1.0 debug: true modules: redis: dsn: redis://${REDIS_USER}:${REDIS_PASSWORD}@${REDIS_HOST}:${REDIS_PORT}/${REDIS_DB} ``` -------------------------------- ### Testing with Automatic In-Memory Server Source: https://github.com/ankorstore/yokai-contrib/blob/main/_autodocs/api-reference/fxgomysqlserver.md This example shows how to test your DAO using the module's automatic in-memory server. It sets up the fxtest environment, populates the server instance, and connects to it for testing queries. ```go package dao_test import ( "context" "database/sql" "testing" "github.com/ankorstore/yokai-contrib/fxgomysqlserver" "github.com/ankorstore/yokai-contrib/fxgomysqlserver/config" "github.com/ankorstore/yokai/fxconfig" _ "github.com/go-sql-driver/mysql" "go.uber.org/fx" "go.uber.org/fx/fxtest" ) func TestUserDAO(t *testing.T) { var srv *server.Server app := fxtest.New( t, fxconfig.FxConfigModule, fxgomysqlserver.FxGoMySQLServerModule, fx.Populate(&srv), ) app.RequireStart() defer app.RequireStop() // Connect to server db, _ := sql.Open("mysql", "user:password@tcp(localhost:3306)/db") defer db.Close() // Test queries row := db.QueryRowContext(context.Background(), "SELECT 1") var result int _ = row.Scan(&result) } ``` -------------------------------- ### Example Usage of FxElasticsearch Module Source: https://github.com/ankorstore/yokai-contrib/blob/main/_autodocs/api-reference/fxelasticsearch.md Demonstrates how to integrate the FxElasticsearchModule into an Fx application and use the injected Elasticsearch client. ```go package main import ( "github.com/ankorstore/yokai-contrib/fxelasticsearch" "github.com/ankorstore/yokai/fxcore" "go.uber.org/fx" ) func main() { app := fxcore.NewBootstrapper().WithOptions( fxelasticsearch.FxElasticsearchModule, fx.Invoke(SearchDocuments), ).Bootstrap() } func SearchDocuments(client *elasticsearch.Client) error { // Use the injected client res, err := client.Search() return err } ``` -------------------------------- ### Redis Configuration Example Source: https://github.com/ankorstore/yokai-contrib/blob/main/_autodocs/api-reference/fxredis.md Example YAML configuration for the Redis module, specifying the Data Source Name (DSN). ```yaml modules: redis: dsn: redis://localhost:6379/0 ``` -------------------------------- ### Publish Event Example Source: https://github.com/ankorstore/yokai-contrib/blob/main/_autodocs/api-reference/fxgcppubsub.md Demonstrates publishing an event to a Pub/Sub topic using the Publisher interface. It includes setting message ordering keys and count thresholds. The data is automatically encoded using the configured codec. ```go func PublishEvent(publisher Publisher) error { ctx := context.Background() event := &Event{ ID: "evt-123", Type: "user.created", Data: map[string]string{"user_id": "usr-456"}, } result, err := publisher.Publish( ctx, "events-topic", event, topic.WithMessageOrderingKey("usr-456"), topic.WithCountThreshold(10), ) if err != nil { return err } // Await publish confirmation messageID, err := result.Get(ctx) return err } ``` -------------------------------- ### GCP Pub/Sub Configuration Example Source: https://github.com/ankorstore/yokai-contrib/blob/main/_autodocs/api-reference/fxgcppubsub.md Illustrates the YAML configuration structure for setting the GCP Project ID for the gcppubsub module. ```yaml modules: gcppubsub: project: id: my-gcp-project ``` -------------------------------- ### Full Yokai Contrib Configuration Example Source: https://github.com/ankorstore/yokai-contrib/blob/main/_autodocs/configuration.md This snippet shows a complete configuration file for Yokai Contrib, detailing settings for multiple integrated modules. It serves as a reference for setting up various services and features. ```yaml app: name: my-app env: dev version: 1.0.0 debug: true modules: elasticsearch: address: http://localhost:9200 redis: dsn: redis://localhost:6379/0 slack: auth_token: xoxb-${SLACK_BOT_TOKEN} app_level_token: xapp-${SLACK_APP_TOKEN} jsonapi: log: enabled: true trace: enabled: false gcppubsub: project: id: my-gcp-project gomysqlserver: config: transport: memory user: testuser password: testpass database: testdb log: enabled: true testcontainer: containers: postgres: image: postgres:15 port: "5432/tcp" environment: postgres_password: secret http: server: errors: obfuscate: false ``` -------------------------------- ### Example: Send Slack Message using FxSlackModule Source: https://github.com/ankorstore/yokai-contrib/blob/main/_autodocs/api-reference/fxslack.md Demonstrates how to use the FxSlackModule to inject a slack.Client and send a message. Ensure the slack.Client is available in the DI container. ```go package main import ( "github.com/ankorstore/yokai-contrib/fxslack" "github.com/slack-go/slack" "go.uber.org/fx" ) func main() { app := fx.New( fxslack.FxSlackModule, fx.Invoke(SendSlackMessage), ) } func SendSlackMessage(client *slack.Client) error { _, _, err := client.PostMessage( "C123456", slack.MsgOptionText("Hello, Slack!", false), ) return err } ``` -------------------------------- ### Register JSON API Routes with Echo Source: https://github.com/ankorstore/yokai-contrib/blob/main/_autodocs/api-reference/fxjsonapi.md Example of bootstrapping the FxJSONAPI and FxHttpServer modules and registering a route that uses the JSON API processor to handle requests and responses. ```go package main import ( "github.com/ankorstore/yokai-contrib/fxjsonapi" "github.com/ankorstore/yokai/fxcore" "github.com/ankorstore/yokai/fxhttpserver" "github.com/labstack/echo/v4" "go.uber.org/fx" ) func main() { app := fxcore.NewBootstrapper().WithOptions( fxjsonapi.FxJSONAPIModule, fxhttpserver.FxHttpServerModule, fx.Invoke(registerRoutes), ).Bootstrap() } func registerRoutes( httpServer *echo.Echo, processor fxjsonapi.Processor, ) { httpServer.POST("/users", func(c echo.Context) error { var user User if err := processor.ProcessRequest(c, &user); err != nil { return err } // Save user... return processor.ProcessResponse(c, 201, user) }) } ``` -------------------------------- ### Example YAML Configuration for Elasticsearch Source: https://github.com/ankorstore/yokai-contrib/blob/main/_autodocs/api-reference/fxelasticsearch.md Shows the structure for configuring the Elasticsearch module in YAML format, including address, username, and password. ```yaml modules: elasticsearch: address: http://localhost:9200 username: elastic password: changeme ``` -------------------------------- ### Go Test with Fx Injection and Config-Based Containers Source: https://github.com/ankorstore/yokai-contrib/blob/main/fxtestcontainer/README.md Illustrates how to integrate fxtestcontainer with Fx dependency injection for configuration-based container creation. This approach simplifies setup by providing the container factory via Fx. ```go func TestWithFxInjection(t *testing.T) { t.Setenv("APP_ENV", "test") var factory fxtestcontainer.ContainerConfigFactory app := fxtest.New( t, fx.NopLogger, fx.Provide( func() (*config.Config, error) { return config.NewDefaultConfigFactory().Create(config.WithFilePaths("./path/to/config")) }, ), fxtestcontainer.FxTestContainerModule, fx.Populate(&factory), ) app.RequireStart() defer app.RequireStop() // Use the injected factory container, err := fxtestcontainer.CreateGenericContainerFromConfig(context.Background(), factory, "redis") require.NoError(t, err) defer container.Terminate(context.Background()) // Test your service... } ``` -------------------------------- ### Custom Wait Strategy for Container Initialization Source: https://github.com/ankorstore/yokai-contrib/blob/main/_autodocs/api-reference/fxtestcontainer.md Shows how to define a custom wait strategy for a container, ensuring it's ready before proceeding. This example uses `wait.ForHTTP` to wait for an Elasticsearch container to become available on a specific port and path, with a defined startup timeout. This is crucial for services that require a specific readiness check. ```go config := &fxtestcontainer.ContainerConfig{ Image: "elasticsearch:8.0", Port: "9200/tcp", WaitingFor: wait.ForHTTP("/"). WithPort("9200/tcp"). WithStartupTimeout(30 * time.Second), } container, _ := fxtestcontainer.CreateGenericContainer(ctx, config) ``` -------------------------------- ### Example: Notify Channel using Slack Client Source: https://github.com/ankorstore/yokai-contrib/blob/main/_autodocs/api-reference/fxslack.md A utility function to send a notification message to a specified Slack channel using a provided slack.Client instance. ```go package service import ( "github.com/slack-go/slack" ) func NotifyChannel(client *slack.Client, channelID, message string) error { _, _, err := client.PostMessage( channelID, slack.MsgOptionText(message, false), ) return err } ``` -------------------------------- ### Register FxGcpPubSub Module Source: https://github.com/ankorstore/yokai-contrib/blob/main/_autodocs/api-reference/fxgcppubsub.md Registers the FxGcpPubSub module with its various providers for clients, codecs, and registries. This setup is essential for dependency injection within an Fx application. ```go var FxGcpPubSubModule = fx.Module( ModuleName, fx.Provide( NewFxGcpPubSubTestServer, NewFxGcpPubSubClient, NewFxGcpPubSubSchemaClient, fx.Annotate(NewFxGcpPubSubDefaultClientFactory, fx.As(new(client.ClientFactory))), fx.Annotate(ack.NewDefaultAckSupervisor, fx.As(new(ack.AckSupervisor))), fx.Annotate(codec.NewDefaultCodecFactory, fx.As(new(codec.CodecFactory))), fx.Annotate(schema.NewDefaultSchemaConfigRegistry, fx.As(new(schema.SchemaConfigRegistry))), fx.Annotate(topic.NewDefaultTopicFactory, fx.As(new(topic.TopicFactory))), fx.Annotate(topic.NewDefaultTopicRegistry, fx.As(new(topic.TopicRegistry))), fx.Annotate(subscription.NewDefaultSubscriptionFactory, fx.As(new(subscription.SubscriptionFactory))), fx.Annotate(subscription.NewDefaultSubscriptionRegistry, fx.As(new(subscription.SubscriptionRegistry))), fx.Annotate(reactor.NewDefaultWaiterSupervisor, fx.As(new(reactor.WaiterSupervisor))), fx.Annotate(NewFxGcpPubSubPublisher, fx.As(new(Publisher))), fx.Annotate(NewFxGcpPubSubSubscriber, fx.As(new(Subscriber))), ), AsPubSubTestServerReactor(ack.NewAckReactor), ) ``` -------------------------------- ### Test Pub/Sub with FX Go Source: https://github.com/ankorstore/yokai-contrib/blob/main/fxgcppubsub/README.md Demonstrates how to set up and run tests using FX Go GCP Pub/Sub. It configures the test environment, populates necessary dependencies, publishes a message, and subscribes to it, asserting the message content and successful acknowledgment. ```go package example_test import ( "context" "testing" "time" "github.com/ankorstore/yokai-contrib/fxgcppubsub" "github.com/ankorstore/yokai-contrib/fxgcppubsub/message" "github.com/ankorstore/yokai-contrib/fxgcppubsub/reactor/ack" "github.com/ankorstore/yokai/fxconfig" "github.com/stretchr/testify/assert" "github.com/foo/bar/internal" "go.uber.org/fx" "go.uber.org/fx/fxtest" ) func TestPubSub(t *testing.T) { t.Setenv("APP_ENV", "test") t.Setenv("APP_CONFIG_PATH", "testdata/config") t.Setenv("GCP_PROJECT_ID", "test-project") var publisher fxgcppubsub.Publisher var subscriber fxgcppubsub.Subscriber var supervisor ack.AckSupervisor ctx := context.Background() // test app internal.RunTest( t, // prepare test topic and subscription fxgcppubsub.PrepareTopicAndSubscription(fxgcppubsub.PrepareTopicAndSubscriptionParams{ TopicID: "test-topic", SubscriptionID: "test-subscription", }), fx.Populate(&publisher, &subscriber, &supervisor), ) // publish to test-topic _, err := publisher.Publish(ctx, "test-topic", "test data") assert.NoError(t, err) // subscribe from test-subscription waiter := supervisor.StartAckWaiter("test-subscription") go subscriber.Subscribe(ctx, "test-subscription", func(ctx context.Context, m *message.Message) { assert.Equal(t, []byte("test data"), m.Data()) m.Ack() }) // wait for subscriber message ack _, err = waiter.WaitMaxDuration(ctx, time.Second) assert.NoError(t, err) } ``` -------------------------------- ### Prepare Topic and Subscription with Schema Source: https://github.com/ankorstore/yokai-contrib/blob/main/_autodocs/api-reference/fxgcppubsub.md Prepares a topic with schema and its subscription in the test server. Use this to set up specific pub/sub configurations for testing. ```go app := fxtest.New( t, fxgcppubsub.FxGcpPubSubModule, fxgcppubsub.PrepareTopicAndSubscriptionWithSchema( fxgcppubsub.PrepareTopicAndSubscriptionWithSchemaParams{ TopicID: "orders-topic", SubscriptionID: "orders-subscription", SchemaID: "order-schema", SchemaConfig: pubsub.SchemaConfig{ Type: pubsub.SchemaAvro, Definition: orderAvroSchema, }, SchemaEncoding: pubsub.EncodingJSON, }, ), ) ``` -------------------------------- ### Prepare Pub/Sub Topic and Subscription in Test Server Source: https://github.com/ankorstore/yokai-contrib/blob/main/_autodocs/api-reference/fxgcppubsub.md Provides an Fx option to prepare both a Pub/Sub topic and its subscription using the test server. Requires topic and subscription identifiers, along with their respective configurations. ```go func PrepareTopicAndSubscription(params PrepareTopicAndSubscriptionParams) fx.Option ``` -------------------------------- ### Available Server Options Source: https://github.com/ankorstore/yokai-contrib/blob/main/_autodocs/api-reference/fxgomysqlserver.md Lists the available functional options for server creation. These include WithConfig, WithLogOutput, and WithTracer for customizing server behavior. ```go `WithConfig(c *config.GoMySQLServerConfig)` | config | Use custom server configuration | `WithLogOutput(w io.Writer)` | io.Writer | Redirect server logs (default: io.Discard) | `WithTracer(t trace.Tracer)` | trace.Tracer | Enable query tracing (default: noop) | ``` -------------------------------- ### Go Test with Configuration-Based Containers Source: https://github.com/ankorstore/yokai-contrib/blob/main/fxtestcontainer/README.md Demonstrates how to load a YAML configuration and use it to create and manage test containers like Redis and PostgreSQL within a Go test function. Ensure the configuration file path is correctly set. ```go package service_test import ( "context" "testing" "github.com/ankorstore/yokai-contrib/fxtestcontainer" "github.com/ankorstore/yokai/config" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) func TestMyService_WithConfigBasedContainers(t *testing.T) { t.Setenv("APP_ENV", "test") ctx := context.Background() // Load configuration cfg, err := config.NewDefaultConfigFactory().Create(config.WithFilePaths("./path/to/config")) require.NoError(t, err) // Create factory factory := fxtestcontainer.NewDefaultContainerConfigFactory(cfg) // Create Redis container from config redisContainer, err := fxtestcontainer.CreateGenericContainerFromConfig(ctx, factory, "redis") require.NoError(t, err) defer redisContainer.Terminate(ctx) // Create PostgreSQL container from config postgresContainer, err := fxtestcontainer.CreateGenericContainerFromConfig(ctx, factory, "postgres") require.NoError(t, err) defer postgresContainer.Terminate(ctx) // Get connection details redisEndpoint, err := redisContainer.Endpoint(ctx, "") require.NoError(t, err) postgresHost, err := postgresContainer.Host(ctx) require.NoError(t, err) postgresPort, err := postgresContainer.MappedPort(ctx, "5432") require.NoError(t, err) // Initialize your service with container endpoints service := NewMyService(redisEndpoint, postgresHost, postgresPort.Port()) // Run your tests err = service.Process(ctx, "test-data") assert.NoError(t, err) } ``` -------------------------------- ### Prepare Pub/Sub Topic with Schema in Test Server Source: https://github.com/ankorstore/yokai-contrib/blob/main/_autodocs/api-reference/fxgcppubsub.md Provides an Fx option to prepare a Pub/Sub topic with an attached schema using the test server. Requires topic and schema identifiers, configurations, and encoding type. ```go func PrepareTopicWithSchema(params PrepareTopicWithSchemaParams) fx.Option ``` -------------------------------- ### Prepare Pub/Sub Schema in Test Server Source: https://github.com/ankorstore/yokai-contrib/blob/main/_autodocs/api-reference/fxgcppubsub.md Provides an Fx option to prepare a Pub/Sub schema using the test server. Requires schema ID and configuration, including type and definition. ```go func PrepareSchema(params PrepareSchemaParams) fx.Option ``` ```go app := fxtest.New( t, fxgcppubsub.FxGcpPubSubModule, fxgcppubsub.PrepareSchema(fxgcppubsub.PrepareSchemaParams{ SchemaID: "user-schema", SchemaConfig: pubsub.SchemaConfig{ Type: pubsub.SchemaAvro, Definition: avroSchema, }, }), ) ``` -------------------------------- ### CreateGenericContainer Function Signature Source: https://github.com/ankorstore/yokai-contrib/blob/main/_autodocs/api-reference/fxtestcontainer.md Function signature for creating and starting a generic Docker container based on a provided configuration. ```go func CreateGenericContainer(ctx context.Context, config *ContainerConfig) (testcontainers.Container, error) ``` -------------------------------- ### Prepare Pub/Sub Topic in Test Server Source: https://github.com/ankorstore/yokai-contrib/blob/main/_autodocs/api-reference/fxgcppubsub.md Provides an Fx option to prepare a Pub/Sub topic using the test server. Requires topic ID and configuration details like message ordering and retention. ```go func PrepareTopic(params PrepareTopicParams) fx.Option ``` -------------------------------- ### CreateGenericContainer Source: https://github.com/ankorstore/yokai-contrib/blob/main/_autodocs/api-reference/fxtestcontainer.md Creates and starts a Docker container based on the provided configuration. It handles validation, port exposure, and setting up a default wait strategy if none is specified. ```APIDOC ## CreateGenericContainer ### Description Creates and starts a container from the provided configuration. It validates the configuration, merges port information, and applies default waiting strategies. ### Method `func CreateGenericContainer(ctx context.Context, config *ContainerConfig) (testcontainers.Container, error)` ### Parameters #### Path Parameters N/A #### Query Parameters N/A #### Request Body N/A ### Request Example ```go package main import ( "context" "github.com/ankorstore/yokai-contrib/fxtestcontainer" "github.com/testcontainers/testcontainers-go/wait" ) func main() { ctx := context.Background() config := &fxtestcontainer.ContainerConfig{ Image: "postgres:15", Port: "5432/tcp", Environment: map[string]string{ "POSTGRES_PASSWORD": "testpass", "POSTGRES_DB": "testdb", }, WaitingFor: wait.ForLog("database system is ready to accept connections"), } container, err := fxtestcontainer.CreateGenericContainer(ctx, config) if err != nil { panic(err) } defer container.Terminate(ctx) // Use container in tests } ``` ### Response #### Success Response - `testcontainers.Container` - A started container instance. - `error` - Nil if successful. #### Response Example N/A (returns a container instance or an error) ### Errors - `ErrContainerImageRequired`: If the `Image` field in `ContainerConfig` is empty. - Other errors related to container startup failures. ``` -------------------------------- ### Custom Mock Behavior with Redismock Source: https://github.com/ankorstore/yokai-contrib/blob/main/_autodocs/api-reference/fxredis.md Shows how to create a custom mock client using `redismock.NewClientMock` and set specific expectations for testing individual logic components. ```go package myservice_test import ( "context" "github.com/go-redis/redismock/v9" "testing" ) func TestCacheLogic(t *testing.T) { client, clientMock := redismock.NewClientMock() // Expect Get to return a value clientMock.ExpectGet("key").SetVal("value") // Test your code val, err := client.Get(context.Background(), "key").Result() if err != nil || val != "value" { t.Fail() } } ``` -------------------------------- ### Subscription Type Definition Source: https://github.com/ankorstore/yokai-contrib/blob/main/_autodocs/api-reference/fxgcppubsub.md Defines the Subscription struct, representing a Pub/Sub subscription with codec support. It provides methods to get the codec, base subscription, apply options, and subscribe to messages. ```go type Subscription struct { // Unexported fields } ``` -------------------------------- ### Configure TCP Transport for Go MySQL Server Source: https://github.com/ankorstore/yokai-contrib/blob/main/fxgomysqlserver/README.md Configure the server to use TCP transport by setting the transport to 'tcp' in the configuration. This example shows the relevant configuration parameters for TCP connections. ```yaml # ./configs/config.yaml modules: gomysqlserver: config: transport: tcp user: user password: password host: localhost port: 3306 database: db ``` -------------------------------- ### Configure fxgomysqlserver Source: https://github.com/ankorstore/yokai-contrib/blob/main/_autodocs/configuration.md Set up the Go MySQL Server module for in-memory or TCP connections. Specify transport, credentials, host, port, and database. ```yaml modules: gomysqlserver: config: transport: tcp user: testuser password: testpass host: localhost port: 3306 database: testdb log: enabled: false trace: enabled: false ``` -------------------------------- ### Publish Avro Encoded Message to GCP Pub/Sub Topic Source: https://github.com/ankorstore/yokai-contrib/blob/main/fxgcppubsub/README.md Publish a struct message to a GCP Pub/Sub topic, automatically encoded as Avro. The struct fields must be tagged with 'avro' and/or 'json' to guide the encoding process. ```go // struct with tags, representing the message type SimpleRecord struct { StringField string `avro:"StringField" json:"StringField"` FloatField float32 `avro:"FloatField" json:"FloatField"` BooleanField bool `avro:"BooleanField" json:"BooleanField"` } // publish on projects/${GCP_PROJECT_ID}/topics/some-topic res, err := publisher.Publish(context.Backgound(), "some-topic", &SimpleRecord{ StringField: "some string", FloatField: 12.34, BooleanField: true, }) ``` -------------------------------- ### Create Elasticsearch Client with Fx Source: https://github.com/ankorstore/yokai-contrib/blob/main/_autodocs/api-reference/fxelasticsearch.md Creates an Elasticsearch client for dependency injection. In test environments, it returns a mock client. Otherwise, it uses the factory to create a real client. ```go func NewFxElasticsearchClient(p FxElasticsearchClientParam) (*elasticsearch.Client, error) ``` -------------------------------- ### Test with Automatic Mock Client Source: https://github.com/ankorstore/yokai-contrib/blob/main/_autodocs/api-reference/fxredis.md Demonstrates testing with the automatically provided mock Redis client in a test environment (APP_ENV=test). It populates both the real client and mock client, sets expectations on the mock, and then tests the client interaction. ```go package myservice_test import ( "context" "testing" "github.com/ankorstore/yokai-contrib/fxredis" "github.com/ankorstore/yokai/fxconfig" "go.uber.org/fx" "go.uber.org/fx/fxtest" ) func TestWithMock(t *testing.T) { t.Setenv("APP_ENV", "test") var client *redis.Client var clientMock redismock.ClientMock app := fxtest.New( t, fxconfig.FxConfigModule, fxredis.FxRedisModule, fx.Populate(&client, &clientMock), ) app.RequireStart() // Configure mock expectations clientMock.ExpectSet("key", "value", 0).SetVal("OK") // Test code err := client.Set(context.Background(), "key", "value", 0).Err() if err != nil { t.Fail() } app.RequireStop() } ``` -------------------------------- ### Advanced Test Container Configuration with Postgres Source: https://github.com/ankorstore/yokai-contrib/blob/main/fxtestcontainer/README.md Create a test container for Postgres with advanced configuration including environment variables and a custom wait strategy. Retrieve connection details for use in tests. ```go func TestWithPostgres(t *testing.T) { ctx := context.Background() config := &fxtestcontainer.ContainerConfig{ Name: "test-postgres", Image: "postgres:13", Port: "5432/tcp", Environment: map[string]string{ "POSTGRES_DB": "testdb", "POSTGRES_USER": "testuser", "POSTGRES_PASSWORD": "testpass", }, WaitingFor: wait.ForLog("database system is ready to accept connections"), } container, err := fxtestcontainer.CreateGenericContainer(ctx, config) require.NoError(t, err) defer container.Terminate(ctx) // Get connection details host, err := container.Host(ctx) require.NoError(t, err) port, err := container.MappedPort(ctx, "5432") require.NoError(t, err) // Use in your tests dsn := fmt.Sprintf("postgres://testuser:testpass@%s:%s/testdb?sslmode=disable", host, port.Port()) // Connect to database and run tests... } ``` -------------------------------- ### NewFxGoMySQLServerConfig Source: https://github.com/ankorstore/yokai-contrib/blob/main/_autodocs/api-reference/fxgomysqlserver.md Creates configuration for the Go MySQL Server module from the Yokai configuration system. ```APIDOC ## NewFxGoMySQLServerConfig ### Description Creates configuration from Yokai configuration system. ### Reads - `modules.gomysqlserver.config.transport` - Transport type (tcp or memory) - `modules.gomysqlserver.config.user` - Database user - `modules.gomysqlserver.config.password` - Database password - `modules.gomysqlserver.config.host` - Bind host - `modules.gomysqlserver.config.port` - Bind port - `modules.gomysqlserver.config.database` - Database name ### Returns - `*config.GoMySQLServerConfig`: Configured settings - `error`: Unknown transport type or configuration error ``` -------------------------------- ### Integration Test with PostgreSQL Container Source: https://github.com/ankorstore/yokai-contrib/blob/main/_autodocs/api-reference/fxtestcontainer.md Demonstrates how to use `CreateGenericContainerFromConfig` within an integration test to spin up a PostgreSQL container. It shows how to retrieve the container's host and mapped port, construct a DSN, and connect to the database to run a simple query. This is useful for testing database interactions. ```go package integration_test import ( "context" "database/sql" "testing" "github.com/ankorstore/yokai-contrib/fxtestcontainer" "github.com/ankorstore/yokai/config" "github.com/testcontainers/testcontainers-go" "github.com/testcontainers/testcontainers-go/wait" ) func TestWithPostgresContainer(t *testing.T) { ctx := context.Background() cfg, _ := config.NewConfig() factory := fxtestcontainer.NewDefaultContainerConfigFactory(cfg) // Create from configuration container, err := fxtestcontainer.CreateGenericContainerFromConfig( ctx, factory, "postgres-test", ) if err != nil { t.Fatalf("failed to create container: %v", err) } defer container.Terminate(ctx) // Get host and port host, _ := container.Host(ctx) port, _ := container.MappedPort(ctx, "5432/tcp") // Connect to database dsn := fmt.Sprintf( "postgres://user:password@%s:%s/testdb?sslmode=disable", host, port.Port(), ) db, _ := sql.Open("postgres", dsn) defer db.Close() // Run tests var result int db.QueryRowContext(ctx, "SELECT 1").Scan(&result) if result != 1 { t.Fail() } } ``` -------------------------------- ### Configure fxtestcontainer for PostgreSQL Source: https://github.com/ankorstore/yokai-contrib/blob/main/_autodocs/configuration.md Set up a PostgreSQL test container using Testcontainers. Define image, ports, environment variables, and command. ```yaml modules: testcontainer: containers: postgres-test: name: integration-postgres image: postgres:15 port: "5432/tcp" exposed_ports: - "5432/tcp" environment: postgres_password: testpass postgres_db: integration_test cmd: - "postgres" - "-c" - "shared_buffers=256MB" ``` -------------------------------- ### Subscribe to Protobuf Messages Source: https://github.com/ankorstore/yokai-contrib/blob/main/fxgcppubsub/README.md Demonstrates how to subscribe to a GCP Pub/Sub topic and decode incoming messages into a generated protobuf struct. Ensure the protobuf stub is generated and available. ```go package internal import ( "context" "fmt" "github.com/ankorstore/yokai-contrib/fxgcppubsub/message" "google.golang.org/protobuf/runtime/protoimpl" ) // generated protobuf stub proto.Message, representing the message type SimpleRecord struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields StringField string `protobuf:"bytes,1,opt,name=string_field,json=stringField,proto3" json:"string_field,omitempty" FloatField float32 `protobuf:"fixed32,2,opt,name=float_field,json=floatField,proto3" json:"float_field,omitempty" BooleanField bool `protobuf:"varint,3,opt,name=boolean_field,json=booleanField,proto3" json:"boolean_field,omitempty" } // subscribe from projects/${GCP_PROJECT_ID}/subscriptions/some-subscription err := subscriber.Subscribe(ctx, "some-subscription", func(ctx context.Context, m *message.Message) { var rec SimpleRecord err = m.Decode(&rec) if err != nil { m.Nack() } fmt.Printf("%v", rec) m.Ack() }) ``` -------------------------------- ### GoMySQLServerOption Source: https://github.com/ankorstore/yokai-contrib/blob/main/_autodocs/api-reference/fxgomysqlserver.md Functional options for server creation, allowing customization of configuration, logging, and tracing. ```APIDOC ## Server Options ### Description Functional options for server creation. ### Available Options | Function | Parameter | Purpose | |---|---|---| | `WithConfig(c *config.GoMySQLServerConfig)` | config | Use custom server configuration | | `WithLogOutput(w io.Writer)` | io.Writer | Redirect server logs (default: io.Discard) | | `WithTracer(t trace.Tracer)` | trace.Tracer | Enable query tracing (default: noop) | ``` -------------------------------- ### PrepareTopic Source: https://github.com/ankorstore/yokai-contrib/blob/main/_autodocs/api-reference/fxgcppubsub.md Helper function to prepare a Pub/Sub topic in the test server. Allows configuration of topic-specific settings like message ordering. ```APIDOC ## PrepareTopic Prepares a Pub/Sub topic in the test server. ### Signature ```go func PrepareTopic(params PrepareTopicParams) fx.Option ``` ### Parameters - **TopicID** (string) - Required - Topic name. - **TopicConfig** (pubsub.TopicConfig) - Optional - Topic configuration (message ordering, retention, etc.). ```