{"id":34125650,"url":"https://github.com/halilbulentorhon/invacache-go","last_synced_at":"2026-05-28T08:31:52.359Z","repository":{"id":320365199,"uuid":"1051557046","full_name":"halilbulentorhon/invacache-go","owner":"halilbulentorhon","description":"High-performance in-memory cache for Go with TTL, distributed invalidation, and zero dependencies.","archived":false,"fork":false,"pushed_at":"2025-10-31T07:59:11.000Z","size":67,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-12-17T09:20:55.878Z","etag":null,"topics":["cache-invalidation","distributed-cache","go","golang","in-memory-cache"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/halilbulentorhon.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-09-06T08:39:12.000Z","updated_at":"2025-10-31T07:55:47.000Z","dependencies_parsed_at":"2025-12-14T23:05:25.310Z","dependency_job_id":null,"html_url":"https://github.com/halilbulentorhon/invacache-go","commit_stats":null,"previous_names":["halilbulentorhon/invacache-go"],"tags_count":5,"template":false,"template_full_name":null,"purl":"pkg:github/halilbulentorhon/invacache-go","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/halilbulentorhon%2Finvacache-go","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/halilbulentorhon%2Finvacache-go/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/halilbulentorhon%2Finvacache-go/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/halilbulentorhon%2Finvacache-go/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/halilbulentorhon","download_url":"https://codeload.github.com/halilbulentorhon/invacache-go/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/halilbulentorhon%2Finvacache-go/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33601380,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-05-28T02:00:06.440Z","response_time":99,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cache-invalidation","distributed-cache","go","golang","in-memory-cache"],"created_at":"2025-12-14T23:04:14.624Z","updated_at":"2026-05-28T08:31:52.344Z","avatar_url":"https://github.com/halilbulentorhon.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# InvaCache-Go\n\nA high-performance, thread-safe, generic in-memory cache library for Go with TTL support, automatic cleanup, and\ndistributed invalidation capabilities.\n\n## Features\n\n- 🚀 **High Performance**: Shard-based architecture for concurrent access\n- 🔧 **Generic Types**: Full support for Go generics (Go 1.21+)\n- ⏰ **TTL Support**: Automatic expiration with configurable cleanup intervals\n- 🔄 **SingleFlight**: Prevents duplicate requests for the same key\n- 🌐 **Distributed Invalidation**: Optional cache invalidation with pluggable drivers (zero deps core)\n- 🧵 **Thread-Safe**: Concurrent read/write operations with minimal locking\n- 📊 **Configurable**: Customizable shard count, capacity, and sweep intervals\n- 📝 **Structured Logging**: Built-in structured logging with configurable levels and formats\n\n## Installation\n\n### Core Library (Zero Dependencies)\n\n```bash\ngo get github.com/halilbulentorhon/invacache-go\n```\n\nThis installs only the core cache functionality with no external dependencies.\n\n### Optional Invalidation Drivers\n\nInvaCache-Go uses a **pluggable driver architecture** to keep the core library dependency-free. Install only the drivers\nyou need:\n\n#### Couchbase Driver\n\n```bash\ngo get github.com/halilbulentorhon/invacache-go/invalidation/drivers/couchbase\n```\n\n#### Redis Driver\n\n```bash\ngo get github.com/halilbulentorhon/invacache-go/invalidation/drivers/redis\n```\n\n### Dependency Isolation\n\n| Usage Scenario     | Dependencies                     |\n|--------------------|----------------------------------|\n| **In-Memory Only** | ✅ Zero dependencies              |\n| **+ Couchbase**    | ✅ Only Couchbase SDK \u0026 cb-pubsub |\n| **+ Redis**        | ✅ Only Redis client              |\n| **+ Both Drivers** | ✅ Both driver dependencies       |\n\nEach driver is a separate module, so you only pull in what you actually use.\n\n## Quick Start\n\n### Basic Usage (No External Dependencies)\n\n```go\npackage main\n\nimport (\n\t\"fmt\"\n\t\"time\"\n\n\t\"github.com/halilbulentorhon/invacache-go\"\n\t\"github.com/halilbulentorhon/invacache-go/config\"\n\t\"github.com/halilbulentorhon/invacache-go/backend/option\"\n)\n\nfunc main() {\n\t// Create cache configuration\n\tcfg := config.InvaCacheConfig{\n\t\tBackendName: \"in-memory\",\n\t\tBackend: \u0026config.BackendConfig{\n\t\t\tInMemory: \u0026config.InMemoryConfig{\n\t\t\t\tShardCount:      16,               // Number of shards for concurrent access\n\t\t\t\tCapacity:        10000,            // Maximum number of items\n\t\t\t\tSweeperInterval: 30 * time.Second, // Cleanup interval\n\t\t\t\tTtl:             \"10m\",            // Default TTL for all items (optional)\n\t\t\t},\n\t\t},\n\t}\n\n\t// Create a new cache instance for string values\n\tcache, err := invacache.NewCache[string](cfg)\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\tdefer cache.Close() // Always cleanup resources\n\n\t// Set a value with TTL\n\terr = cache.Set(\"user:123\", \"John Doe\", option.WithTTL(5*time.Minute))\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\n\t// Get a value\n\tvalue, err := cache.Get(\"user:123\")\n\tif err != nil {\n\t\tfmt.Printf(\"Error: %v\\n\", err)\n\t\treturn\n\t}\n\tfmt.Printf(\"User: %s\\n\", value)\n\n\t// Get or load pattern\n\tuser, err := cache.GetOrLoad(\"user:456\", func(key string) (string, time.Duration, error) {\n\t\t// This function is called only if the key is not in cache\n\t\t// Simulate database lookup\n\t\treturn \"Jane Doe\", 10 * time.Minute, nil\n\t})\n\tif err != nil {\n\t\tpanic(err)\n\t}\n\tfmt.Printf(\"Loaded user: %s\\n\", user)\n}\n```\n\n## API Reference\n\n### Cache Interface\n\n```go\ntype Cache[V any] interface {\n    Get(key string) (V, error)\n    GetOrLoad(key string, loader LoaderFunc[V]) (V, error)\n    Set(key string, value V, options ...option.OptFnc) error\n    Delete(key string, options ...option.DelOptFnc) error\n    Clear(options ...option.ClrOptFnc) error\n    Close() error\n}\n```\n\n### Configuration\n\n```go\ntype InvaCacheConfig struct {\n    BackendName  string              `json:\"backendName\"`\n    Backend      *BackendConfig      `json:\"backend\"`\n    Invalidation *InvalidationConfig `json:\"invalidation,omitempty\"`\n}\n\ntype BackendConfig struct {\n    InMemory *InMemoryConfig `json:\"inMemory\"`\n}\n\ntype InMemoryConfig struct {\n    ShardCount      int           `json:\"shardCount\"`      // Default: 8\n    SweeperInterval time.Duration `json:\"sweeperInterval\"` // Default: 10 minutes\n    Capacity        int           `json:\"capacity\"`        // Default: 1000\n    Ttl             string        `json:\"ttl\"`             // Default TTL for all items (e.g., \"10m\", \"1h\")\n}\n\n### Options\n\n**Set Options:**\n- `option.WithTTL(duration)` - Set expiration time for specific key\n- `option.WithNoExpiration()` - Set item to never expire\n- `option.WithInvalidation()` - Trigger distributed invalidation on Set\n\n**Delete Options:**\n- `option.WithDeleteInvalidation()` - Trigger distributed invalidation on Delete\n\n**Clear Options:**\n- `option.WithClearInvalidation()` - Trigger distributed invalidation on Clear\n\n## Advanced Usage\n\n### Custom Types\n\n```go\ntype User struct {\n    ID   int    `json:\"id\"`\n    Name string `json:\"name\"`\n}\n\ncache, err := invacache.NewCache[User](cfg)\nif err != nil {\n\tpanic(err)\n}\ndefer cache.Close() // Always cleanup resources\n\nuser := User{ID: 1, Name: \"John\"}\ncache.Set(\"user:1\", user, option.WithTTL(time.Hour))\n\n// Clear all cache\nerr = cache.Clear()\nif err != nil {\n\tpanic(err)\n}\n\n// Clear with distributed invalidation\nerr = cache.Clear(option.WithClearInvalidation())\nif err != nil {\n\tpanic(err)\n}\n```\n\n### Structured Logging\n\nInvaCache-Go includes built-in structured logging to help you monitor cache operations and troubleshoot issues.\n\n#### Production Logging (JSON format, Info level)\n\n```go\ncache, err := invacache.NewCache[string](cfg)\nif err != nil {\n\tpanic(err)\n}\n```\n\n#### Development Logging (Text format, Debug level)\n\n```go\n// Note: NewCache function handles backend selection based on BackendName\n// Use NewCache with custom logger configuration for development\ncache, err := invacache.NewCache[string](cfg)\nif err != nil {\n\tpanic(err)\n}\n```\n\n#### Log Levels\n\n- **debug**: Detailed operation logs (cache hits/misses, individual operations)\n- **info**: General information (cache initialization, invalidation events)\n- **warn**: Warning messages (invalidation failures)\n- **error**: Error conditions (cache operation failures)\n\n#### Sample Production Output (JSON)\n\n```json\n{\"time\":\"2025-09-06T13:07:07.846723+03:00\",\"level\":\"INFO\",\"msg\":\"initializing inmemory cache\",\"component\":\"inmemory-cache\",\"shard_count\":16,\"capacity\":10000}\n{\"time\":\"2025-09-06T13:07:07.847048+03:00\",\"level\":\"INFO\",\"msg\":\"invalidation initialized successfully\",\"component\":\"inmemory-cache\",\"type\":\"couchbase\"}\n```\n\n#### Sample Development Output (Text, Debug)\n\n```\ntime=2025-09-06T13:11:32.172+03:00 level=DEBUG msg=\"cache set operation\" component=inmemory-cache key=user:123\ntime=2025-09-06T13:11:32.172+03:00 level=DEBUG msg=\"cache hit\" component=inmemory-cache key=user:123\ntime=2025-09-06T13:11:32.172+03:00 level=DEBUG msg=\"cache delete successful\" component=inmemory-cache key=user:123\n```\n\n### Distributed Invalidation\n\nInvaCache-Go supports **pluggable invalidation drivers** to keep your core library dependency-free. Each driver is a\nseparate module that you install only when needed.\n\n**Available Drivers:**\n\n#### Couchbase Invalidation Driver (using cb-pubsub)\n\n#### Redis Invalidation Driver (using Redis Pub/Sub)\n\nInstall the Couchbase invalidation driver separately:\n\n```bash\ngo get github.com/halilbulentorhon/invacache-go/invalidation/drivers/couchbase\n```\n\nThen use it in your application:\n\n```go\nimport (\n    \"github.com/halilbulentorhon/invacache-go\"\n    \"github.com/halilbulentorhon/invacache-go/config\"\n    \n    // Import the Couchbase invalidation driver\n    _ \"github.com/halilbulentorhon/invacache-go/invalidation/drivers/couchbase\"\n)\n\ncfg := config.InvaCacheConfig{\n    BackendName: \"in-memory\",\n    Backend: \u0026config.BackendConfig{\n        InMemory: \u0026config.InMemoryConfig{\n            ShardCount: 16,\n            Capacity:   10000,\n        },\n    },\n    Invalidation: \u0026config.InvalidationConfig{\n        Type: \"couchbase\",\n        DriverConfig: map[string]any{\n            \"ConnectionString\": \"localhost:8091\",\n            \"Username\":         \"admin\",\n            \"Password\":         \"password\",\n            \"BucketName\":       \"default\",\n            \"CollectionName\":   \"_default\",\n            \"ScopeName\":        \"_default\",\n            \"GroupName\":        \"my-cache-group\",\n        },\n    },\n}\n\ncache, err := invacache.NewCache[string](cfg)\nif err != nil {\n\tpanic(err)\n}\n\n// Important: Always close the cache to properly cleanup resources\ndefer cache.Close() // This will stop invalidation goroutines and cleanup connections\n```\n\nThe Couchbase driver uses the [cb-pubsub](https://github.com/halilbulentorhon/cb-pubsub) library for reliable\ndistributed messaging.\n\n**Important Notes:**\n\n- Invalidation subscription runs in a separate goroutine (non-blocking)\n- Always call `cache.Close()` to properly cleanup resources and stop background goroutines\n- **Resilient Operation**: Cache operations never fail due to invalidation issues\n- **Driver Responsibility**: Retry logic and reconnection are handled by the invalidation driver (cb-pubsub)\n- **Graceful Degradation**: Cache works locally when invalidation is unavailable\n\nInstall the Redis invalidation driver separately:\n\n```bash\ngo get github.com/halilbulentorhon/invacache-go/invalidation/drivers/redis\n```\n\nThen use it in your application:\n\n```go\nimport (\n    \"time\"\n    \n    \"github.com/halilbulentorhon/invacache-go\"\n    \"github.com/halilbulentorhon/invacache-go/config\"\n    \n    // Import the Redis invalidation driver\n    _ \"github.com/halilbulentorhon/invacache-go/invalidation/drivers/redis\"\n)\n\ncfg := config.InvaCacheConfig{\n    BackendName: \"in-memory\",\n    Backend: \u0026config.BackendConfig{\n        InMemory: \u0026config.InMemoryConfig{\n            ShardCount: 16,\n            Capacity:   10000,\n        },\n    },\n    Invalidation: \u0026config.InvalidationConfig{\n        Type: \"redis\",\n        DriverConfig: map[string]any{\n            \"Address\":     \"localhost:6379\",\n            \"Password\":    \"\",\n            \"DB\":          0,\n            \"Channel\":     \"invacache:invalidation\",\n            \"PoolSize\":    10,\n            \"MaxRetries\":  3,\n            \"DialTimeout\": 5 * time.Second,\n        },\n    },\n}\n\ncache, err := invacache.NewCache[string](cfg)\nif err != nil {\n\tpanic(err)\n}\ndefer cache.Close() // Always cleanup resources\n```\n\nThe Redis driver uses Redis's native Pub/Sub mechanism for real-time distributed messaging.\n\n**Redis Driver Benefits:**\n\n- **High Performance**: Redis's optimized pub/sub implementation\n- **Real-time**: Immediate invalidation propagation\n- **Scalable**: Supports unlimited cache instances\n- **Simple Setup**: Minimal Redis configuration required\n- **Reliable**: Built on Redis's proven infrastructure\n\n## Performance\n\nInvaCache-Go is designed for high-performance scenarios:\n\n- **Sharded Architecture**: Reduces lock contention by distributing keys across multiple shards\n- **Minimal Allocations**: Efficient memory usage with pre-allocated structures\n- **SingleFlight**: Prevents thundering herd problems for expensive operations\n- **Concurrent Sweeping**: Background cleanup doesn't block cache operations\n\n## Contributing\n\nContributions are welcome! Please feel free to submit a Pull Request.\n\n## License\n\nThis project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhalilbulentorhon%2Finvacache-go","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhalilbulentorhon%2Finvacache-go","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhalilbulentorhon%2Finvacache-go/lists"}