mcache

package module
v1.0.4 Latest Latest
Warning

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

Go to latest
Published: Dec 27, 2020 License: MIT Imports: 10 Imported by: 0

README

Manifest Cache - Fast offline-first apps

Manifest Cache (or MCache) is a disk-backed in-memory document store written in Go. It aims to support offline-first applications and improve both bandwidth consumption and latency for multi-tenant applications that serve siloed data over HTTP.

It is designed to directly serve end-user HTTP requests, replicating their server-stored data to their client devices. The primary intended usage pattern is users initially downloading their personal working set and storing it locally, then subsequently querying for updates. For applications with largely or entirely siloed datasets, this distribution strategy can save massive amounts of bandwidth and latency compared to traditional methods.

How it works

MCache stores documents, which are opaque blobs decorated with ID and UpdatedAt properties, in independent collections called indexes. Special documents in an index called manifests hold lists of other document IDs.

Indexes are created with an HTTP POST request, and documents (including manifests) are updated with HTTP PUT requests. Updates to multiple documents in the same index may be batched in a single request. Documents must be provided in full; MCache is unaware of the encoding structure of document bodies and cannot merge document bodies.

A query to MCache includes an index ID, a manifest ID, and a timestamp. MCache will respond with any documents in the manifest that have been updated since the given timestamp. Documents are always delivered in full. Documents cannot be deleted, but they can be updated with a Deleted property and an empty Body. Indexes cannot be deleted via the API, but since each index is contained in a single standalone file on disk, index files can be deleted while the server is not running.

HTTP API

POST /i/:indexID

Create Index

  • Body: Empty
  • Response: New Index
$ curl -X POST 'http://localhost:1337/i/example'
{"id":"example"}
PUT /i/:indexID

Update Indexed Documents

  • Body: JSON-encoded array of Document objects (UpdatedAt on given Documents is ignored since this property is set automatically on write)
  • Response: JSON-encoded DocSet object containing updated Documents
$ curl -X PUT -d '[{"id": "a", "body": "RG9jdW1lbnQgQQ==", "deleted": false }, { "id": "m", "body": "eyJhIjp7fX0=", "deleted": false }]' 'http://localhost:1337/i/example'
{
  "docs": {
    "a": {
      "id": "a",
      "updatedAt": 1609096924,
      "body": "RG9jdW1lbnQgQQ==",
      "deleted": false
    },
    "m": {
      "id": "m",
      "updatedAt": 1609096924,
      "body": "eyJhIjp7fX0=",
      "deleted": false
    }
  },
  "start": 1609096924,
  "end": 1609096924
}
GET /i/:indexID/m/:manifestID/@/:updatedAfter

Query Indexed Documents

  • Response: JSON-encoded DocSet object containing Documents that satisfy the query
$ curl 'http://localhost:1337/i/example/m/m/@/0'
{
  "docs": {
    "a": {
      "id": "a",
      "updatedAt": 1609096924,
      "body": "RG9jdW1lbnQgQQ==",
      "deleted": false
    },
    "m": {
      "id": "m",
      "updatedAt": 1609096924,
      "body": "eyJhIjp7fX0=",
      "deleted": false
    }
  },
  "start": 1609096924,
  "end": 1609096924
}

License

Released under The MIT License (see LICENSE.txt).

Copyright 2020 Duncan Smith

Documentation

Index

Constants

This section is empty.

Variables

View Source
var DefaultConfig = Config{
	LRUCacheSize:  10000,
	MaxIndexCount: 100000,
	MaxIndexSize:  100000,
	DataDir:       "./.mcache",
	Host:          "localhost",
	Port:          "1337",
}

DefaultConfig describes a default configuration for MCache

Functions

This section is empty.

Types

type Config

type Config struct {
	LRUCacheSize  int
	MaxIndexCount int
	MaxIndexSize  int
	DataDir       string
	Host          string
	Port          string
}

Config describes the configuration of an MCache instance

type DocSet

type DocSet struct {
	Docs  map[string]Document `json:"docs"`
	Start Timestamp           `json:"start"`
	End   Timestamp           `json:"end"`
}

DocSet is a map of document IDs to documents

func NewDocSet

func NewDocSet(docs ...Document) *DocSet

NewDocSet returns a DocSet for a set of docs

func (*DocSet) Add

func (d *DocSet) Add(docs ...Document) *DocSet

Add adds a Document to the DocSet

func (*DocSet) Merge

func (d *DocSet) Merge(docs *DocSet) *DocSet

Merge adds all Documents in a given DocSet to the DocSet

type Document

type Document struct {
	ID        string    `json:"id"`
	UpdatedAt Timestamp `json:"updatedAt"`
	Body      []byte    `json:"body"`
	Deleted   bool      `json:"deleted"`
}

Document is a resource that can be accessed by users

type IDSet

type IDSet map[string]SetEntry

IDSet is an emulated Set (map of strings to empty structs) of document ID

func NewIDSet

func NewIDSet(ids ...string) IDSet

NewIDSet returns an IDSet for a set of IDs

type Index

type Index struct {
	ID string `json:"id"`
	// contains filtered or unexported fields
}

Index represents a collection of documents managed by the cache

func NewIndex

func NewIndex(id string, docs *du.Duramap, cacheSize int) (*Index, error)

NewIndex returns a new Index

func (*Index) Get

func (i *Index) Get(id string) (doc *Document, err error)

Get gets the index document with the given ID

func (*Index) GetAll

func (i *Index) GetAll() (docs *DocSet, err error)

GetAll gets all the index documents

func (*Index) GetManifest

func (i *Index) GetManifest(id string) (*Manifest, error)

GetManifest returns a manifest document

func (*Index) Keys

func (i *Index) Keys() IDSet

Keys returns all the keys in an index

func (*Index) LRUKeys

func (i *Index) LRUKeys() IDSet

LRUKeys returns all the keys in an index's LRU cache

func (*Index) LoadDocuments

func (i *Index) LoadDocuments(docIDs IDSet, updatedAfter Timestamp) (*DocSet, error)

LoadDocuments will, for a given set of document IDs, query the LRU cache for the latest matching versions and fetch the rest from the store

func (*Index) Query

func (i *Index) Query(manifestID string, updatedAfter Timestamp) (*DocSet, error)

Query returns any documents matching the manifest with the given id that were updated after the given timestamp

func (*Index) SoftDelete

func (i *Index) SoftDelete(ids IDSet) (*DocSet, error)

SoftDelete updates the index documents with a tombstone value

func (*Index) Update

func (i *Index) Update(docs *DocSet) (*DocSet, error)

Update updates the index documents with the latest versions

type IndexManager

type IndexManager struct {
	*mutable.RW

	Indexes map[string]*Index
	// contains filtered or unexported fields
}

IndexManager manages a collection of Indexes

func NewIndexManager

func NewIndexManager(config Config) *IndexManager

NewIndexManager initializes an IndexManager at the given path

func (*IndexManager) GetIndex

func (m *IndexManager) GetIndex(id string) *Index

GetIndex returns the index with the given id, or nil if one is not found

func (*IndexManager) Open

func (m *IndexManager) Open(id string) (*Index, error)

Open creates or returns an index with the given id

func (*IndexManager) Scan

func (m *IndexManager) Scan() error

Scan will open any indexes whose data files are in the configured directory

type MCache

type MCache struct {
	Config
	// contains filtered or unexported fields
}

MCache is an HTTP-accessible object cache

func NewMCache

func NewMCache(config Config) (*MCache, error)

NewMCache returns an MCache with the given configuration

func (*MCache) CreateIndex

func (m *MCache) CreateIndex(id string) (*Index, error)

CreateIndex creates a new index with the given ID

func (*MCache) Get

func (m *MCache) Get(indexID string, docID string) (*Document, error)

Get gets a document in an index

func (*MCache) GetAll

func (m *MCache) GetAll(indexID string) (*DocSet, error)

GetAll gets all documents in an index

func (*MCache) GetIndex

func (m *MCache) GetIndex(id string) *Index

GetIndex returns an internal Index object

func (*MCache) Keys

func (m *MCache) Keys(indexID string) (IDSet, error)

Keys returns all keys in an index

func (*MCache) Query

func (m *MCache) Query(indexID string, manifestID string, updatedAfter Timestamp) (*DocSet, error)

Query gets all index documents matching a given manifest that were updated after a given timestamp

func (*MCache) SoftDelete

func (m *MCache) SoftDelete(indexID string, ids IDSet) (*DocSet, error)

SoftDelete overwrites documents in the given index with the given IDs with tombstone values

func (*MCache) Update

func (m *MCache) Update(indexID string, docs *DocSet) (*DocSet, error)

Update updates the index with the given documents

type Manifest

type Manifest struct {
	ID          string `json:"id"`
	UpdatedAt   int64  `json:"updatedAt"`
	DocumentIDs IDSet  `json:"documentIDs"`
}

Manifest is a user's set of accessible document IDs

func DecodeManifest

func DecodeManifest(d Document) (*Manifest, error)

DecodeManifest returns a Manifest that is stored in a Document

func (*Manifest) Add

func (m *Manifest) Add(documentID string)

Add a document to the manifest

func (*Manifest) Encode added in v1.0.2

func (m *Manifest) Encode() (*Document, error)

Encode returns a Document that stores a Manifest

type SetEntry

type SetEntry struct{}

A SetEntry is an empty struct that represents membership in a set

type Timestamp

type Timestamp = int64

Timestamp is a Unix milliseconds offset

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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