xmap

package module
v0.3.0 Latest Latest
Warning

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

Go to latest
Published: Aug 23, 2024 License: MIT Imports: 4 Imported by: 0

README

xmap

Go Reference Go Report Card Go Tests

A generic and thread-safe Go map with automatic key expiration.

Installation

go get -u github.com/mdawar/xmap

Usage

New Map
// Create a map with the default configuration.
m := xmap.New[string, int]()
// Stop the cleanup goroutine and clear the map.
defer m.Stop()
Create
// Create new entries in the map.
m.Set("a", 1, time.Minute) // Key that expires in 1 minute.
m.Set("b", 2, 0)           // Key that never expires (0 TTL).

// Replace a key.
m.Set("a", 3, time.Hour) // Replace key (New value and expiration time).
Update
// Update the value without changing the expiration time.
// Reports whether the key was updated (Key exists).
ok := m.Update("b", 4)
Get
// Get the value if the key exists and has not expired.
// The second return value reports whether the key exists.
value, ok := m.Get("a")

// Get the value with the expiration time.
// The third return value reports whether the key exists.
value, expiration, ok := m.GetWithExpiration("a")
// If the key never expires, it will have a zero expiration time value.
neverExpires := expiration.IsZero()
Delete
// Delete a key from the map.
m.Delete("a")

// Delete all the keys from the map.
m.Clear()
Length
total := m.Len()
Iteration
for key, value := range m.All() {
	fmt.Println("Key:", key, "-", "Value:", value)
}
Remove Expired Keys
// Expired keys are automatically removed at regular intervals.
// Additionally, the removal of expired keys can be manually triggered.
removed := m.RemoveExpired() // Returns the number of removed keys.

Configuration

Name Type Description
CleanupInterval time.Duration Interval at which expired keys are removed (Default: 5 minutes).
InitialCapacity int Initial map capacity hint (Passed to make()).
TimeSource xmap.Time Custom time source (Useful for testing).

Example:

package xmap

import (
	"time"

	"github.com/mdawar/xmap"
)

func main() {
	m := xmap.NewWithConfig[string, int](xmap.Config{
		CleanupInterval: 10 * time.Minute,
		InitialCapacity: 10_000_000,
		TimeSource:      mockTime,
	})
	defer m.Stop()
}

Tests

make test

Or:

go test -cover -race

Benchmarks

make benchmark

Or:

go test -bench .

Documentation

Overview

Package xmap provides a generic, thread-safe map with automatic key expiration.

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Config

type Config struct {
	// CleanupInterval is the interval at which the expired keys are removed.
	// Default: 5 minutes.
	CleanupInterval time.Duration
	// InitialCapacity is the initial capacity hint passed to make when creating
	// the map. It does not bound the size of the map, It will create a map with
	// an initial space to hold the specified number of elements.
	InitialCapacity int
	// TimeSource is the time source used by the map for key expiration.
	// This is only useful for testing.
	// Default: system time.
	TimeSource Time
}

Config represents the Map configuration.

type Map

type Map[K comparable, V any] struct {
	// contains filtered or unexported fields
}

Map is a thread-safe map with automatic key expiration.

Example
package main

import (
	"fmt"
	"time"

	"github.com/mdawar/xmap"
)

func main() {
	// Create a map with the default configuration.
	m := xmap.New[string, int]()
	defer m.Stop() // Stop the cleanup goroutine and clear the map.

	// Create new entries in the map.
	m.Set("a", 1, time.Minute) // Key that expires in 1 minute.
	m.Set("b", 2, 0)           // Key that never expires (0 TTL).

	// Replace a key.
	m.Set("a", 3, time.Hour) // Replace key (New value and expiration time).

	// Update the value without changing the expiration time.
	if ok := m.Update("b", 4); ok {
		fmt.Println("Key updated successfully")
	} else {
		fmt.Println("Key does not exist")
	}

	// Get the value if the key exists and has not expired.
	if value, ok := m.Get("a"); ok {
		fmt.Println("Value:", value)
	} else {
		fmt.Println("Key does not exist")
	}

	// Get the value with the expiration time.
	if value, expiration, ok := m.GetWithExpiration("a"); ok {
		// If the key never expires, it will have a zero expiration time value.
		fmt.Println("Key expires:", !expiration.IsZero())
		fmt.Println("Value:", value, "-", "Expiration:", expiration)
	} else {
		fmt.Println("Key does not exist")
	}

	total := m.Len() // Length of the map.

	fmt.Println("Total entries in the map:", total)

	m.Delete("a") // Delete a key from the map.
	m.Clear()     // Delete all the keys from the map.

	// Expired keys are automatically removed at regular intervals.
	// Additionally, the removal of expired keys can be manually triggered.
	removed := m.RemoveExpired()

	fmt.Println("Total keys removed:", removed)
}
Output:

func New

func New[K comparable, V any]() *Map[K, V]

New creates a new Map instance with the default configuration.

func NewWithConfig

func NewWithConfig[K comparable, V any](cfg Config) *Map[K, V]

NewWithConfig creates a new Map instance with the specified configuration.

Example
package main

import (
	"time"

	"github.com/mdawar/xmap"
)

func main() {
	m := xmap.NewWithConfig[string, int](xmap.Config{
		CleanupInterval: 10 * time.Minute, // Change the default cleanup interval.
		InitialCapacity: 1_000_000,        // Initial capacity hint (Passed to make).
	})
	defer m.Stop()
}
Output:

func (*Map[K, V]) All added in v0.3.0

func (m *Map[K, V]) All() iter.Seq2[K, V]

All returns an iterator over key-value pairs from the Map.

Only the entries that have not expired are produced during the iteration.

Similar to the map type, the iteration order is not guaranteed.

Example
package main

import (
	"fmt"

	"github.com/mdawar/xmap"
)

func main() {
	m := xmap.New[string, int]()
	defer m.Stop()

	for k, v := range m.All() {
		fmt.Println("Key:", k, "-", "Value:", v)
	}
}
Output:

func (*Map[K, V]) CleanupActive

func (m *Map[K, V]) CleanupActive() bool

CleanupActive reports whether the cleanup goroutine is active.

func (*Map[K, V]) Clear

func (m *Map[K, V]) Clear()

Clear removes all the entries from the Map.

func (*Map[K, V]) Delete

func (m *Map[K, V]) Delete(key K)

Delete removes a key from the Map.

func (*Map[K, V]) Get

func (m *Map[K, V]) Get(key K) (V, bool)

Get returns the value associated with the key.

The second bool return value reports whether the key exists in the Map.

func (*Map[K, V]) GetWithExpiration

func (m *Map[K, V]) GetWithExpiration(key K) (V, time.Time, bool)

GetWithExpiration returns the value and expiration time of the key.

The third bool return value reports whether the key exists in the Map.

func (*Map[K, V]) Len

func (m *Map[K, V]) Len() int

Len returns the length of the Map.

The length of the Map is the total number of keys, including the expired keys that have not been removed yet.

To get the length excluding the number of expired keys, call Map.RemoveExpired before calling this method.

func (*Map[K, V]) RemoveExpired

func (m *Map[K, V]) RemoveExpired() int

RemoveExpired checks the Map keys and removes the expired ones.

It returns the number of keys that were removed.

func (*Map[K, V]) Set

func (m *Map[K, V]) Set(key K, value V, ttl time.Duration)

Set creates or replaces a key-value pair in the Map.

A key can be set to never expire with a ttl value of 0.

func (*Map[K, V]) Stop

func (m *Map[K, V]) Stop()

Stop halts the background cleanup goroutine and clears the Map. It should be called when the Map is no longer needed.

This method is safe to be called multiple times.

A stopped Map should not be re-used, a new Map should be created instead.

func (*Map[K, V]) Stopped

func (m *Map[K, V]) Stopped() bool

Stopped reports whether the Map is stopped.

Expired keys are not removed automatically in a stopped Map.

func (*Map[K, V]) Update

func (m *Map[K, V]) Update(key K, value V) bool

Update changes the value of the key while preserving the expiration time.

The return value reports whether there was an update (Key exists).

type Ticker

type Ticker interface {
	// C returns the channel on which the ticks are delivered.
	C() <-chan time.Time
	// Stop turns off the ticker.
	Stop()
}

A Ticker holds a channel that delivers "ticks" of a clock at intervals.

type Time

type Time interface {
	// Now returns the current time.
	Now() time.Time
	// NewTicker returns a new [Ticker] containing a channel that
	// will send the current time on the channel after each tick.
	NewTicker(time.Duration) Ticker
}

Time represents a time source.

Jump to

Keyboard shortcuts

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