From 56f804c0ca894ba463fc78b4249ab37c7f7d08d2 Mon Sep 17 00:00:00 2001 From: MohitKatare-protean Date: Wed, 28 May 2025 17:12:09 +0530 Subject: [PATCH] Added logs, comments and issue fix Fixed issue for the interface not implemented for the provider while loading the plugin --- pkg/plugin/implementation/cache/cache.go | 17 ++- pkg/plugin/implementation/cache/cmd/plugin.go | 15 ++- test.go | 103 ++++++++++++++++++ 3 files changed, 130 insertions(+), 5 deletions(-) create mode 100644 test.go diff --git a/pkg/plugin/implementation/cache/cache.go b/pkg/plugin/implementation/cache/cache.go index c8c374a..7007492 100644 --- a/pkg/plugin/implementation/cache/cache.go +++ b/pkg/plugin/implementation/cache/cache.go @@ -7,10 +7,11 @@ import ( "os" "time" + "github.com/beckn/beckn-onix/pkg/log" "github.com/redis/go-redis/v9" ) -// Global variable for the Redis client, can be overridden in tests +// RedisCl global variable for the Redis client, can be overridden in tests var RedisCl *redis.Client // RedisClient is an interface for Redis operations that allows mocking @@ -23,14 +24,17 @@ type RedisClient interface { Close() error } +// Config holds the configuration required to connect to Redis. type Config struct { Addr string } +// Cache wraps a Redis client to provide basic caching operations. type Cache struct { Client RedisClient } +// Error variables to describe common failure modes. var ( ErrEmptyConfig = errors.New("empty config") ErrAddrMissing = errors.New("missing required field 'Addr'") @@ -38,6 +42,7 @@ var ( ErrConnectionFail = errors.New("failed to connect to Redis") ) +// validate checks if the provided Redis configuration is valid. func validate(cfg *Config) error { if cfg == nil { return ErrEmptyConfig @@ -48,6 +53,8 @@ func validate(cfg *Config) error { return nil } +// RedisClientFunc is a function variable that creates a Redis client based on the provided configuration. +// It can be overridden for testing purposes. var RedisClientFunc = func(cfg *Config) RedisClient { return redis.NewClient(&redis.Options{ Addr: cfg.Addr, @@ -56,7 +63,9 @@ var RedisClientFunc = func(cfg *Config) RedisClient { }) } +// New initializes and returns a Cache instance along with a close function to release resources. func New(ctx context.Context, cfg *Config) (*Cache, func() error, error) { + log.Debugf(ctx, "Initializing Cache with config: %+v", cfg) if err := validate(cfg); err != nil { return nil, nil, err } @@ -64,24 +73,30 @@ func New(ctx context.Context, cfg *Config) (*Cache, func() error, error) { client := RedisClientFunc(cfg) if _, err := client.Ping(ctx).Result(); err != nil { + log.Errorf(ctx, err, "Failed to ping Redis server") return nil, nil, fmt.Errorf("%w: %v", ErrConnectionFail, err) } + log.Infof(ctx, "Cache connection to Redis established successfully") return &Cache{Client: client}, client.Close, nil } +// Get retrieves the value for the specified key from Redis. func (c *Cache) Get(ctx context.Context, key string) (string, error) { return c.Client.Get(ctx, key).Result() } +// Set stores the given key-value pair in Redis with the specified TTL (time to live). func (c *Cache) Set(ctx context.Context, key, value string, ttl time.Duration) error { return c.Client.Set(ctx, key, value, ttl).Err() } +// Delete removes the specified key from Redis. func (c *Cache) Delete(ctx context.Context, key string) error { return c.Client.Del(ctx, key).Err() } +// Clear removes all keys in the currently selected Redis database. func (c *Cache) Clear(ctx context.Context) error { return c.Client.FlushDB(ctx).Err() } diff --git a/pkg/plugin/implementation/cache/cmd/plugin.go b/pkg/plugin/implementation/cache/cmd/plugin.go index fda5c97..4cd5869 100644 --- a/pkg/plugin/implementation/cache/cmd/plugin.go +++ b/pkg/plugin/implementation/cache/cmd/plugin.go @@ -4,6 +4,7 @@ import ( "context" "errors" + "github.com/beckn/beckn-onix/pkg/log" "github.com/beckn/beckn-onix/pkg/plugin/definition" "github.com/beckn/beckn-onix/pkg/plugin/implementation/cache" ) @@ -16,14 +17,20 @@ func (c cacheProvider) New(ctx context.Context, config map[string]string) (defin if ctx == nil { return nil, nil, errors.New("context cannot be nil") } - // Create cache.Config directly from map - validation is handled by cache.New cacheConfig := &cache.Config{ Addr: config["addr"], } - - return cache.New(ctx, cacheConfig) + log.Debugf(ctx, "Cache config mapped: %+v", cacheConfig) + cache, closer, err := cache.New(ctx, cacheConfig) + if err != nil { + log.Errorf(ctx, err, "Failed to create cache instance") + return nil, nil, err + } + + log.Infof(ctx, "Cache instance created successfully") + return cache, closer, nil } // Provider is the exported plugin instance -var Provider definition.CacheProvider = cacheProvider{} \ No newline at end of file +var Provider = cacheProvider{} diff --git a/test.go b/test.go new file mode 100644 index 0000000..3a82846 --- /dev/null +++ b/test.go @@ -0,0 +1,103 @@ +package main + +import ( + "context" + "fmt" + "plugin" + "time" + + "github.com/beckn/beckn-onix/pkg/plugin/definition" +) + +func main() { + ctx := context.Background() + + // Path to the compiled plugin .so file + // Adjust the path accordingly + pluginPath := "pkg/plugin/implementation/cache.so" + + // Open the plugin + p, err := plugin.Open(pluginPath) + if err != nil { + fmt.Printf("Failed to open plugin: %v\n", err) + return + } + + // Lookup the 'Provider' symbol + symProvider, err := p.Lookup("Provider") + if err != nil { + fmt.Printf("Failed to lookup 'Provider': %v\n", err) + return + } + + // Assert that the symbol implements the CacheProvider interface + provider, ok := symProvider.(definition.CacheProvider) + if !ok { + fmt.Println("Plugin 'Provider' does not implement CacheProvider interface.") + return + } + fmt.Println("Successfully loaded CacheProvider plugin.") + + // Setup config + config := map[string]string{ + "addr": "localhost:6379", // Adjust to your Redis instance + } + + // Create a new cache instance using the plugin provider + cacheInstance, cleanup, err := provider.New(ctx, config) + if err != nil { + fmt.Printf("Error creating cache instance: %v\n", err) + return + } + defer func() { + if cleanup != nil { + _ = cleanup() + } + }() + + fmt.Println("Cache instance created successfully.") + + // Test Set + key := "plugin_test_key" + value := "plugin_test_value" + ttl := 10 * time.Second + + err = cacheInstance.Set(ctx, key, value, ttl) + if err != nil { + fmt.Printf("Set failed: %v\n", err) + return + } + fmt.Println("Set operation successful.") + + // Test Get + got, err := cacheInstance.Get(ctx, key) + if err != nil { + fmt.Printf("Get failed: %v\n", err) + return + } + fmt.Printf("Got value: %s\n", got) + + // Test Delete + err = cacheInstance.Delete(ctx, key) + if err != nil { + fmt.Printf("Delete failed: %v\n", err) + return + } + fmt.Println("Delete operation successful.") + + // Test Clear + // Add a key to test Clear + err = cacheInstance.Set(ctx, "another_plugin_key", "another_plugin_value", ttl) + if err != nil { + fmt.Printf("Set for clear test failed: %v\n", err) + return + } + fmt.Println("Added key for clear test.") + + err = cacheInstance.Clear(ctx) + if err != nil { + fmt.Printf("Clear failed: %v\n", err) + return + } + fmt.Println("Clear operation successful.") +}