dgocacheler package - github.com/CreativeUnicorns/dgocacheler - Go Packages

dgocacheler

package module
v1.0.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 13, 2025 License: MIT Imports: 5 Imported by: 0

README

go Go Reference

dgocacheler

A high-performance, concurrency-safe cache for storing Discord messages by channel, designed for seamless integration with the discordgo library.

Features

  • Thread-safe operations: Fine-grained channel-level locking for maximum concurrency
  • High performance: Optimized for minimal overhead in both single and multi-threaded scenarios
  • Memory efficient: Smart memory management with minimal allocations
  • Duplicate prevention: Automatic detection and handling of duplicate messages
  • Flexible API: Both safe and ultra-fast access methods for different use cases
  • Backward compatible: Smooth transition from previous versions

Performance

Benchmarks show significant improvements over previous versions:

  • 46% faster for concurrent read/write operations
  • 391% faster for multi-channel operations
  • 99% reduction in memory allocations for multi-channel scenarios
  • Zero-allocation read operations

Installation

go get github.com/CreativeUnicorns/dgocacheler@v1.0.0

Usage

Basic Usage
// Get the global cache
cache := dgocacheler.GetGlobalCache()

// Add a message to the cache
err := cache.AddMessage("channel123", message)
if err != nil {
    log.Printf("Failed to add message: %v", err)
}

// Add multiple messages at once
err = cache.AddMessages("channel123", messages)
if err != nil {
    log.Printf("Failed to add messages: %v", err)
}

// Retrieve messages
messages, err := cache.GetMessages("channel123")
if err != nil {
    if errors.Is(err, dgocacheler.ErrCacheMiss) {
        log.Printf("No messages in channel")
    } else {
        log.Printf("Error retrieving messages: %v", err)
    }
}

// Retrieve limited number of most recent messages
messages, err = cache.GetMessagesLimit("channel123", 10)
if err != nil {
    log.Printf("Error retrieving messages: %v", err)
}

// Set maximum messages per channel
err = cache.SetMaxMessages(500)
if err != nil {
    log.Printf("Error setting max messages: %v", err)
}

// Clear a channel's messages
err = cache.ClearChannel("channel123")
if err != nil {
    log.Printf("Error clearing channel: %v", err)
}
Performance-Critical Usage

For performance-critical code paths:

// Ultra-fast message retrieval (unsafe for long-term reference)
messages, err := cache.GetMessagesUnsafe("channel123")
if err != nil {
    log.Printf("Error retrieving messages: %v", err)
}
Backward Compatibility

Code written for previous versions continues to work:

// Legacy code still works
dgocacheler.Cache.AddMessage("channel123", message)

// But new code should use
dgocacheler.GetGlobalCache().AddMessage("channel123", message)

For more examples, refer to the examples/ directory.

Implementation Details

  • True circular buffer: Efficient O(1) operations for all common operations
  • Optimized locking: Minimized lock scopes to reduce contention
  • Atomic operations: Lock-free access to configuration values
  • Smart slice handling: Direct slice referencing when possible

Contributing

Contributions are welcome! Please feel free to submit a pull request.

License

Distributed under the MIT License. See LICENSE file for more information.

Documentation

Overview

This file provides backward compatibility for existing code

Package cacheler provides a concurrency-safe cache designed specifically for storing Discord messages by channel. It integrates smoothly with the discordgo package.

The dgocacheler package ensures that all operations are safe to use concurrently and manages memory efficiently by enforcing a maximum number of messages per channel.

The package is designed to be simple to use and easy to integrate with existing chatbot handlers code. The dgocacheler package also provides a global `Cache` that can be used across multiple packages to help avoid circular dependencies.

Package dgocacheler provides a concurrency-safe cache for storing Discord messages by channel.

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrNilMessage     = errors.New("message cannot be nil")
	ErrInvalidChannel = errors.New("invalid channel ID")
	ErrCacheMiss      = errors.New("channel not found in cache")
	ErrInvalidLimit   = errors.New("limit must be greater than zero")
)

Common errors returned by the MessageCache

View Source
var Cache interface {
	// Deprecated.
	//
	// Use this instead of Cache directly:
	//      cache := dgocachler.GetGlobalCache()
	//      cache.AddMessage()
	AddMessage(channelID string, message *discordgo.Message) error
	// Deprecated.
	//
	// Use this instead of Cache directly:
	//      cache := dgocachler.GetGlobalCache()
	//      cache.AddMessages()
	AddMessages(channelID string, messages []*discordgo.Message) error
	// Deprecated.
	//
	// Use this instead of Cache directly:
	//      cache := dgocachler.GetGlobalCache()
	//      cache.GetMessages()
	GetMessages(channelID string) ([]*discordgo.Message, error)
	// Deprecated.
	//
	// Use this instead of Cache directly:
	//      cache := dgocachler.GetGlobalCache()
	//      cache.GetMessagesLimit()
	GetMessagesLimit(channelID string, limit int) ([]*discordgo.Message, error)
	// Deprecated.
	//
	// Use this instead of Cache directly:
	//      cache := dgocachler.GetGlobalCache()
	//      cache.ClearChannel()
	ClearChannel(channelID string) error
	// Deprecated.
	//
	// Use this instead of Cache directly:
	//      cache := dgocachler.GetGlobalCache()
	//      cache.SetMaxMessages()
	SetMaxMessages(maxMessages int) error
}

Cache is maintained for backward compatibility with existing code. New code should use GetGlobalCache() instead.

Deprecated: This interface is deprecated and will be removed in future versions.

View Source
var TestHelpers = struct {
	// GenerateMessages creates n test messages
	GenerateMessages func(n int) []*discordgo.Message
}{
	GenerateMessages: func(n int) []*discordgo.Message {
		messages := make([]*discordgo.Message, n)
		for i := 0; i < n; i++ {
			messages[i] = &discordgo.Message{
				ID:      fmt.Sprintf("msg-%d", i),
				Content: fmt.Sprintf("This is test message %d with some content to simulate a real message.", i),
				Author: &discordgo.User{
					ID:       fmt.Sprintf("user-%d", i%100),
					Username: fmt.Sprintf("User%d", i%100),
				},
				ChannelID: "test-channel",
			}
		}
		return messages
	},
}

TestHelpers contains utility functions for testing and benchmarking

Functions

This section is empty.

Types

type ChannelCache added in v1.0.0

type ChannelCache struct {
	sync.RWMutex
	// contains filtered or unexported fields
}

ChannelCache represents a cache for a single channel's messages

type MessageCache

type MessageCache struct {
	sync.RWMutex // Embedding RWMutex to provide global locking
	// contains filtered or unexported fields
}

MessageCache holds Discord messages organized by channel ID. It supports concurrent access.

func GetGlobalCache added in v1.0.0

func GetGlobalCache() *MessageCache

GetGlobalCache returns the singleton global cache instance, initializing it if necessary

func NewMessageCache

func NewMessageCache(maxMessages int) *MessageCache

NewMessageCache creates a new MessageCache with a specified maximum number of messages per channel. If maxMessages is <= 0, it will be set to a default of 100.

func (*MessageCache) AddMessage

func (c *MessageCache) AddMessage(channelID string, message *discordgo.Message) error

AddMessage adds a single message to the cache for a specific channel.

func (*MessageCache) AddMessages

func (c *MessageCache) AddMessages(channelID string, messages []*discordgo.Message) error

AddMessages adds multiple messages to the cache for a specific channel.

func (*MessageCache) ClearChannel added in v1.0.0

func (c *MessageCache) ClearChannel(channelID string) error

ClearChannel removes all cached messages for a specific channel

func (*MessageCache) GetMessages

func (c *MessageCache) GetMessages(channelID string) ([]*discordgo.Message, error)

GetMessages retrieves all messages for a given channel from the cache. This implementation provides both safety and performance by offering different access methods.

func (*MessageCache) GetMessagesLimit

func (c *MessageCache) GetMessagesLimit(channelID string, limit int) ([]*discordgo.Message, error)

GetMessagesLimit retrieves up to a specified number of recent messages for a given channel.

func (*MessageCache) GetMessagesUnsafe added in v1.0.0

func (c *MessageCache) GetMessagesUnsafe(channelID string) ([]*discordgo.Message, error)

GetMessagesUnsafe retrieves all messages for a given channel without copying data. This is much faster but less safe, and should only be used in scenarios where the returned slice won't be modified and will be used briefly.

func (*MessageCache) SetMaxMessages

func (c *MessageCache) SetMaxMessages(maxMessages int) error

SetMaxMessages sets the maximum number of messages to store per channel in the cache.

Directories

Path Synopsis
examples
basic command
import command

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL