redis

package module
v0.0.0-...-e7bb29b Latest Latest
Warning

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

Go to latest
Published: Jan 29, 2019 License: MIT Imports: 11 Imported by: 0

README


Becoming a full Redis implementation in Go

This project started to see how easy it is to implement a full Redis clone in Go. As one of the side effects, imagine you could write redis modules in Go, that would be awesome!

Get involved!

This project is in work-in-progress, so share ideas, code and have fun.

The goal is to have all features and commands like the actual redis written in C have. We are searching contributors!

Documentation

godoc: https://godoc.org/github.com/redis-go/redis

Getting Started

You can already test out the API.

To install, run:

go get -u github.com/redis-go/redis
Roadmap
  • Client connection / request / respond
  • RESP protocol
  • able to register commands
  • in-mem database
  • active key expirer
  • Implementing data structures
    • String
    • List
    • Set
    • Sorted Set
    • Hash
    • ...
  • Tests
    • For existing commands
    • For key expirer
  • Alpha Release
TODO beside Roadmap
  • Persistence
  • Redis config
    • Default redis config format
    • YAML support
    • Json support
  • Pub/Sub
  • Redis modules
  • Benchmarks
  • master slaves
  • cluster
  • ...

Documentation

Index

Constants

View Source
const (
	SyntaxErr         = "ERR syntax error"
	InvalidIntErr     = "ERR value is not an integer or out of range"
	WrongTypeErr      = "WRONGTYPE Operation against a key holding the wrong kind of value"
	WrongNumOfArgsErr = "ERR wrong number of arguments for '%s' command"
)
View Source
const ListType = uint64(1)
View Source
const ListTypeFancy = "list"
View Source
const StringType = uint64(0)
View Source
const StringTypeFancy = "string"

Variables

This section is empty.

Functions

func DelCommand

func DelCommand(c *Client, cmd redcon.Command)

func GetCommand

func GetCommand(c *Client, cmd redcon.Command)

func LPopCommand

func LPopCommand(c *Client, cmd redcon.Command)

func LPushCommand

func LPushCommand(c *Client, cmd redcon.Command)

func LRangeCommand

func LRangeCommand(c *Client, cmd redcon.Command)

func PingCommand

func PingCommand(c *Client, cmd redcon.Command)

func RPopCommand

func RPopCommand(c *Client, cmd redcon.Command)

func RPushCommand

func RPushCommand(c *Client, cmd redcon.Command)

func Run

func Run(addr string) error

Run runs the default redis server. Initializes the default redis if not already.

func SetCommand

func SetCommand(c *Client, cmd redcon.Command)

SET key value [NX] [XX] [EX <seconds>] [PX <milliseconds>]

func TimeExpired

func TimeExpired(expireAt time.Time) bool

TimeExpired check if a timestamp is older than now.

func TtlCommand

func TtlCommand(c *Client, cmd redcon.Command)

Types

type Accept

type Accept func(c *Client) bool

Accept is called when a Client tries to connect and before everything else, the Client connection will be closed instantaneously if the function returns false.

type Client

type Client struct {
	// contains filtered or unexported fields
}

A connected Client.

func (*Client) ClientId

func (c *Client) ClientId() ClientId

ClientId get the client id.

func (*Client) Conn

func (c *Client) Conn() redcon.Conn

The client's connection.

func (*Client) Db

func (c *Client) Db() *RedisDb

Db gets the clients selected database.

func (*Client) DbId

func (c *Client) DbId() DatabaseId

DbId gets the clients selected database id.

func (*Client) FreeClient

func (c *Client) FreeClient()

Disconnects and removes a Client.

func (*Client) Mu

func (c *Client) Mu() *sync.RWMutex

Mu the mutex.

func (*Client) Redis

func (c *Client) Redis() *Redis

Redis gets the redis instance.

func (*Client) SelectDb

func (c *Client) SelectDb(db DatabaseId)

SelectDb selects the clients database.

type ClientId

type ClientId uint64

Client id

type Clients

type Clients map[ClientId]*Client

Client map

type CmdFlag

type CmdFlag uint

Command flag type.

const (
	CMD_WRITE             CmdFlag = iota + 1 /* "w" flag */
	CMD_READONLY                             /* "r" flag */
	CMD_DENYOOM                              /* "m" flag */
	CMD_MODULE                               /* Command exported by module. */
	CMD_ADMIN                                /* "a" flag */
	CMD_PUBSUB                               /* "p" flag */
	CMD_NOSCRIPT                             /* "s" flag */
	CMD_RANDOM                               /* "R" flag */
	CMD_SORT_FOR_SCRIPT                      /* "S" flag */
	CMD_LOADING                              /* "l" flag */
	CMD_STALE                                /* "t" flag */
	CMD_SKIP_MONITOR                         /* "M" flag */
	CMD_ASKING                               /* "k" flag */
	CMD_FAST                                 /* "F" flag */
	CMD_MODULE_GETKEYS                       /* Use the modules getkeys interface. */
	CMD_MODULE_NO_CLUSTER                    /* Deny on Redis Cluster. */
)

Command flags. Please check the command table defined in the redis.c file for more information about the meaning of every flag.

type Command

type Command struct {
	// contains filtered or unexported fields
}

A command can be registered.

func NewCommand

func NewCommand(name string, handler CommandHandler, flags ...CmdFlag) *Command

func (*Command) Name

func (cmd *Command) Name() string

Gets registered commands name.

type CommandHandler

type CommandHandler func(c *Client, cmd redcon.Command)

The CommandHandler is triggered when the received command equals a registered command.

However the CommandHandler is executed by the Handler, so if you implement an own Handler make sure the CommandHandler is called.

type Commands

type Commands map[string]*Command

Commands map

type DatabaseId

type DatabaseId uint

Database id

type Expirer

type Expirer struct {
	// contains filtered or unexported fields
}

func NewKeyExpirer

func NewKeyExpirer(r *Redis) *Expirer

func (*Expirer) Redis

func (e *Expirer) Redis() *Redis

Redis gets the redis instance.

func (*Expirer) Start

func (e *Expirer) Start(tick time.Duration, randomKeys int, againPercentage int)

Start starts the Expirer.

tick - How fast is the cleaner triggered.

randomKeys - Amount of random expiring keys to get checked.

againPercentage - If more than x% of keys were expired, start again in same tick.

func (*Expirer) Stop

func (e *Expirer) Stop()

Stop stops the

type ExpiringKeys

type ExpiringKeys map[string]time.Time

Keys with expire timestamp.

type Handler

type Handler func(c *Client, cmd redcon.Command)

A Handler is called when a request is received and after Accept (if Accept allowed the connection by returning true).

For implementing an own handler see the default handler as a perfect example in the createDefault() function.

type Item

type Item interface {
	// The pointer to the value.
	Value() interface{}

	// The id of the type of the Item.
	// This need to be constant for the type because it is
	// used when de-/serializing item from/to disk.
	Type() uint64
	// The type of the Item as readable string.
	TypeFancy() string

	// OnDelete is triggered before the key of the item is deleted.
	// db is the affected database.
	OnDelete(key *string, db *RedisDb)
}

The item interface. An item is the value of a key.

type KeyExpirer

type KeyExpirer interface {
	Start(tick time.Duration, keyNum int, againPercentage int)
	Stop()
}

type Keys

type Keys map[string]Item

Key-Item map

type List

type List struct {
	// contains filtered or unexported fields
}

func NewList

func NewList() *List

func (*List) LIndex

func (l *List) LIndex(index int) (*string, error)

LIndex see redis doc

func (*List) LInsert

func (l *List) LInsert(isBefore bool, pivot, value *string) int

LInsert see redis doc

func (*List) LLen

func (l *List) LLen() int

LLen returns number of elements.

func (*List) LPop

func (l *List) LPop() (*string, bool)

LPop returns popped value and false - returns true if list is now emptied so the key can be deleted.

func (*List) LPush

func (l *List) LPush(values ...*string) int

LPush returns the length of the list after the push operation.

func (*List) LRange

func (l *List) LRange(start int, end int) []string

LRange see redis doc

func (*List) LRem

func (l *List) LRem(count int, value *string) int

LRem see redis doc

func (*List) LSet

func (l *List) LSet(index int, value *string) error

LSet see redis doc

func (*List) LTrim

func (l *List) LTrim(start int, end int) bool

LTrim see redis docs - returns true if list is now emptied so the key can be deleted.

func (*List) OnDelete

func (l *List) OnDelete(key *string, db *RedisDb)

func (*List) RPop

func (l *List) RPop() (*string, bool)

RPop returns popped value and false - returns true if list is now emptied so the key can be deleted.

func (*List) RPush

func (l *List) RPush(values ...*string) int

RPush returns the length of the list after the push operation.

func (*List) Type

func (l *List) Type() uint64

func (*List) TypeFancy

func (l *List) TypeFancy() string

func (*List) Value

func (l *List) Value() interface{}

type OnClose

type OnClose func(c *Client, err error)

OnClose is called when a Client connection is closed.

type Redis

type Redis struct {
	// contains filtered or unexported fields
}

This is the redis server.

func Default

func Default() *Redis

Default redis server. Initializes the default redis if not already. You can change the fields or value behind the pointer of the returned redis pointer to extend/change the default.

func (*Redis) AcceptFn

func (r *Redis) AcceptFn() Accept

Gets the accept func.

func (*Redis) Clients

func (r *Redis) Clients() Clients

Clients gets the current connected clients.

func (*Redis) Command

func (r *Redis) Command(name string) *Command

Command returns the registered command or nil if not exists.

func (*Redis) CommandExists

func (r *Redis) CommandExists(cmds ...string) bool

CommandExists checks if one or more commands are registered.

func (*Redis) CommandHandlerFn

func (r *Redis) CommandHandlerFn(name string) CommandHandler

CommandHandlerFn returns the CommandHandler of cmd.

func (*Redis) Commands

func (r *Redis) Commands() Commands

Commands returns the commands map.

func (*Redis) FlushCommands

func (r *Redis) FlushCommands()

FlushCommands removes all commands.

func (*Redis) HandlerFn

func (r *Redis) HandlerFn() Handler

Gets the handler func.

func (*Redis) KeyExpirer

func (r *Redis) KeyExpirer() KeyExpirer

func (*Redis) Mu

func (r *Redis) Mu() *sync.RWMutex

The mutex of the redis.

func (*Redis) NewClient

func (r *Redis) NewClient(conn redcon.Conn) *Client

NewClient creates new client and adds it to the redis.

func (*Redis) NextClientId

func (r *Redis) NextClientId() ClientId

NextClientId atomically gets and increments a counter to return the next client id.

func (*Redis) OnCloseFn

func (r *Redis) OnCloseFn() OnClose

Gets the onclose func.

func (*Redis) RedisDb

func (r *Redis) RedisDb(dbId DatabaseId) *RedisDb

RedisDb gets the redis database by its id or creates and returns it if not exists.

func (*Redis) RedisDbs

func (r *Redis) RedisDbs() RedisDbs

RedisDbs gets all redis databases.

func (*Redis) RegisterCommand

func (r *Redis) RegisterCommand(cmd *Command)

RegisterCommand adds a command to the redis instance. If cmd already exists the handler is overridden.

func (*Redis) RegisterCommands

func (r *Redis) RegisterCommands(cmds []*Command)

RegisterCommands adds commands to the redis instance. If a cmd already exists the handler is overridden.

func (*Redis) Run

func (r *Redis) Run(addr string) error

Run runs the redis server.

func (*Redis) RunTLS

func (r *Redis) RunTLS(addr string, tls *tls.Config) error

Run runs the redis server with tls.

func (*Redis) SetAcceptFn

func (r *Redis) SetAcceptFn(new Accept)

Sets the accept func. Live updates (while redis is running) works.

func (*Redis) SetHandlerFn

func (r *Redis) SetHandlerFn(new Handler)

Sets the handler func. Live updates (while redis is running) works.

func (*Redis) SetKeyExpirer

func (r *Redis) SetKeyExpirer(ke KeyExpirer)

func (*Redis) SetOnCloseFn

func (r *Redis) SetOnCloseFn(new OnClose)

Sets the onclose func. Live updates (while redis is running) works.

func (*Redis) UnknownCommandFn

func (r *Redis) UnknownCommandFn() UnknownCommand

UnknownCommandFn returns the UnknownCommand function.

func (*Redis) UnregisterCommand

func (r *Redis) UnregisterCommand(name string)

UnregisterCommand removes a command.

type RedisDb

type RedisDb struct {
	// contains filtered or unexported fields
}

A redis database. There can be more than one in a redis instance.

func NewRedisDb

func NewRedisDb(id DatabaseId, r *Redis) *RedisDb

NewRedisDb creates a new db.

func (*RedisDb) Delete

func (db *RedisDb) Delete(keys ...*string) int

Deletes a key, returns number of deleted keys.

func (*RedisDb) DeleteExpired

func (db *RedisDb) DeleteExpired(keys ...*string) int

func (*RedisDb) Exists

func (db *RedisDb) Exists(key *string) bool

Check if key exists.

func (*RedisDb) Expired

func (db *RedisDb) Expired(key *string) bool

Expired only check if a key can and is expired.

func (*RedisDb) Expires

func (db *RedisDb) Expires(key *string) bool

Check if key has an expiry set.

func (*RedisDb) ExpiringKeys

func (db *RedisDb) ExpiringKeys() ExpiringKeys

ExpiringKeys gets keys with an expiry set and their timeout.

func (*RedisDb) Expiry

func (db *RedisDb) Expiry(key *string) time.Time

Expiry gets the expiry of the key has one.

func (*RedisDb) Get

func (db *RedisDb) Get(key *string) Item

Returns the item by the key or nil if key does not exists.

func (*RedisDb) GetOrExpire

func (db *RedisDb) GetOrExpire(key *string, deleteIfExpired bool) Item

GetOrExpire gets the item or nil if expired or not exists. If 'deleteIfExpired' is true the key will be deleted.

func (*RedisDb) HasExpiringKeys

func (db *RedisDb) HasExpiringKeys() bool

HasExpiringKeys checks if db has any expiring keys.

func (*RedisDb) Id

func (db *RedisDb) Id() DatabaseId

Id gets the db id.

func (*RedisDb) IsEmpty

func (db *RedisDb) IsEmpty() bool

IsEmpty checks if db is empty.

func (*RedisDb) Keys

func (db *RedisDb) Keys() Keys

Keys gets all keys in this db.

func (*RedisDb) Mu

func (db *RedisDb) Mu() *sync.RWMutex

Mu gets the mutex.

func (*RedisDb) Redis

func (db *RedisDb) Redis() *Redis

Redis gets the redis instance.

func (*RedisDb) Set

func (db *RedisDb) Set(key *string, i Item, expires bool, expiry time.Time)

Sets a key with an item which can have an expiration time.

type RedisDbs

type RedisDbs map[DatabaseId]*RedisDb

Redis databases map

type String

type String struct {
	// contains filtered or unexported fields
}

func NewString

func NewString(value *string) *String

func (*String) OnDelete

func (s *String) OnDelete(key *string, db *RedisDb)

func (*String) Type

func (s *String) Type() uint64

func (*String) TypeFancy

func (s *String) TypeFancy() string

func (*String) Value

func (s *String) Value() interface{}

type UnknownCommand

type UnknownCommand func(c *Client, cmd redcon.Command)

Is called when a request is received, after Accept and if the command is not registered.

However UnknownCommand is executed by the Handler, so if you implement an own Handler make sure to include UnknownCommand.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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