vvmap

package module
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Jul 9, 2020 License: MIT Imports: 2 Imported by: 1

README

vvmap GoDoc

vvmap is a Go implementation of a delta-based CRDT map as written about in "∆-CRDTs: Making δ-CRDTs Delta-Based", "Dotted Version Vectors: Logical Clocks for Optimistic Replication", and Tyler McMullen's excellent talk "The Anatomy of a Distributed System".

Usage:

package main

import (
	"fmt"
	"strings"
 	"github.com/hankjacobs/vvmap"
)

func main() {
	lexicographicConflictResolver := func(key string, left, right vvmap.Record) bool {
		leftVal := left.Value.(string)
		rightVal := right.Value.(string)
		return strings.Compare(leftVal, rightVal) > 0 // choose left if lexicographically greater
	}

	alice := vvmap.New("alice", lexicographicConflictResolver)
	bob := vvmap.New("bob", lexicographicConflictResolver)
	tim := vvmap.New("tim", lexicographicConflictResolver)

	// concurrently update everyone -- causes a conflict, should all resolve to "turkey" since
	// lexicographically greatest
	alice.Set("lunch", "turkey")
	bob.Set("lunch", "ham")
	tim.Set("lunch", "chicken")

	// get records that Bob has but Alice doesn't
	delta := bob.Delta(alice.Version())
	alice.Merge(delta)

	// get records that Tim has but Alice doesn't
	delta = tim.Delta(alice.Version())
	alice.Merge(delta)

	// sync bob
	bob.Merge(alice.Delta(bob.Version())) // alice is most up-to-date so no need to sync with Tim

	// sync tim
	tim.Merge(alice.Delta(tim.Version()))

	fmt.Println("alice:", alice.Get("lunch"))
	fmt.Println("bob:", bob.Get("lunch"))
	fmt.Println("tim:", tim.Get("lunch"))
}

Documentation

Overview

Package vvmap is an implementation of a delta-based CRDT map as written about in "∆-CRDTs: Making δ-CRDTs Delta-Based" (http://nova-lincs.di.fct.unl.pt/system/publication_files/files/000/000/666/original/a12-van_der_linde.pdf?1483708753) and "Dotted Version Vectors: Logical Clocks for Optimistic Replication" (https://arxiv.org/pdf/1011.5808.pdf).

Example
aliceID := ID("alice")
bobID := ID("bob")
timID := ID("tim")

lexicographicResolver := func(key string, left, right Record) bool {
	leftVal := left.Value.(string)
	rightVal := right.Value.(string)
	return strings.Compare(leftVal, rightVal) > 0 // choose left if lexicographically greater
}

alice := New(aliceID, lexicographicResolver)
bob := New(bobID, lexicographicResolver)
tim := New(timID, lexicographicResolver)

// concurrently update everyone -- causes a conflict, should all resolve to "turkey" since
// lexicographically greatest
alice.Set("lunch", "turkey")
bob.Set("lunch", "ham")
tim.Set("lunch", "chicken")

// sync alice
alice.Merge(bob.Delta(alice.Version()))
alice.Merge(tim.Delta(alice.Version()))

// sync bob
bob.Merge(alice.Delta(bob.Version())) // alice is most up-to-date so no need to sync with Tim

// sync tim
tim.Merge(alice.Delta(tim.Version()))

fmt.Println("alice:", alice.Get("lunch"))
fmt.Println("bob:", bob.Get("lunch"))
fmt.Println("tim:", tim.Get("lunch"))
Output:

alice: turkey
bob: turkey
tim: turkey

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type ChooseLeftConflictResolver

type ChooseLeftConflictResolver func(key string, left, right Record) bool

ChooseLeftConflictResolver is a function which returns whether the left Record should be used to resolve the conflict. It can be assumed that left and right have the same key. This must deterministically choose the same item no matter the order.

type Delta

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

Delta are the most recent records seen between since and current

type ID

type ID string

ID of node. An ID must be unique across all nodes sharing the map.

type Map

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

Map is a delta based CRDT map

func New

func New(id ID, resolver ChooseLeftConflictResolver) *Map

New returns a new Map with the specified ID and conflict resolver

func (*Map) Delta

func (v *Map) Delta(since VersionVector) Delta

Delta generates a list of records that have not been seen by the specified version vector.

func (*Map) Get

func (v *Map) Get(key string) interface{}

Get returns the value set for key or nil if it does not exist

func (*Map) GobDecode

func (v *Map) GobDecode(buf []byte) error

implement gob encode/decode interface

func (*Map) GobEncode

func (v *Map) GobEncode() ([]byte, error)

implement gob encode/decode interface

func (*Map) ID

func (v *Map) ID() ID

ID is the map's ID

func (*Map) Keys

func (v *Map) Keys() []string

Keys returns all the keys contained in the map

func (*Map) Merge

func (v *Map) Merge(delta Delta)

Merge merges a delta into the map

func (*Map) Set

func (v *Map) Set(key string, value interface{})

Set sets a value for a key

func (*Map) Version

func (v *Map) Version() VersionVector

Version is the map's version

type Record

type Record struct {
	Key   string
	Value interface{}
	Dot   VVDot
}

Record is a record stored in a VVMap

type VVDot

type VVDot struct {
	SourceID ID
	Version  uint64
}

VVDot is a version vector dot used to represent an event with the specified version from a node with SourceID

type VersionVector

type VersionVector map[ID]uint64

VersionVector vector of node versions keyed by their ID

Jump to

Keyboard shortcuts

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