Hamok

https://www.hamok.dev

View project on GitHub

User Manual

Hamok / HamokEmitter / HamokMap / HamokQueue / HamokRecord / HamokRemoteMap

Table of Contents

Overview

HamokMap is a class that provides a replicated storage solution across instances, allowing for key-value pair manipulation with event-driven notifications.

Create a HamokMap instance

You need a Hamok to create a Map. Here is how you can create a HamokMap instance:

const map = hamok.createMap<string, number>({
  mapId: "exampleMap",
});

Configuration

At the time of creation, you can pass the following configuration options:

const map = hamok.createMap<string, number>({
	/**
	 * The unique identifier for the map.
	 */
	mapId: 'map1',

	/**
	 * Optional. The timeout duration in milliseconds for requests.
	 *
	 * DEFAULT: 5000
	 */
	requestTimeoutInMs: 5000,

	/**
	 * Optional. The maximum number of keys allowed in request or response messages.
	 *
	 * DEFAULT: 0 means infinity
	 */
	maxOutboundMessageKeys: 1000,

	/**
	 * Optional. The maximum number of values allowed in request or response messages.
	 *
	 * DEFAULT: 0 means infinity
	 */
	maxOutboundMessageValues: 100,

	/**
	 * Optional. A base map to be used as the initial state of the map.
	 *
	 * DEFAULT: a new and empty BaseMap instance
	 */
	baseMap: new BaseMap<K, V>(),

	/**
	 * Optional. A codec for encoding and decoding keys in the map.
	 *
	 * DEFAULT: JSON codec
	 */
	keyCodec: {
		encode: (key: K) => Buffer.from(JSON.stringify(key)),
		decode: (data: Uint8Array) => JSON.parse(Buffer.from(data).toString()),
	}

	/**
	 * Optional. A codec for encoding and decoding values in the map.
	 *
	 * DEFAULT: JSON codec
	 */
	valueCodec?: {
		encode: (value: V) => Buffer.from(JSON.stringify(value)),
		decode: (data: Uint8Array) => JSON.parse(Buffer.from(data).toString()),
	}

	/**
	 * Optional. A function to determine equality between two values.
	 * Used for custom equality checking.
	 */
	equalValues: (a: V, b: V) => a === b,
});

API Reference HamokMap<K, V>

A class representing a distributed map with various methods for manipulating and accessing the stored entries.

Properties

  • id: string - The unique identifier of the map.
  • closed: boolean - Indicates whether the map is closed.
  • size: number - The number of entries in the map.
  • isEmpty: boolean - Indicates whether the map is empty.
  • equalValues: (a: V, b: V) => boolean - A function to compare values for equality.
  • connection: HamokConnection<string, string> - The connection used by the map.
  • ready: Promise<void> - A promise that resolves when the map is initialized and ready to use.

Events

The HamokMap class extends EventEmitter and emits the following events:

  • insert - Emitted when a new entry is inserted.
  • update - Emitted when an entry is updated.
  • remove - Emitted when an entry is removed.
  • clear - Emitted when all entries are cleared.
  • close - Emitted when the map is closed.

Methods

  • close(): void

    • Closes the map and releases any held resources.
  • keys(): IterableIterator<K>

    • Returns an iterator over the keys in the map.
  • clear(): Promise<void>

    • Clears all entries in the map.
  • get(key: K): V | undefined

    • Retrieves the value associated with the specified key.
  • removeIf(key: K, value: V): Promise<boolean>

    • Removes the entry if the current value matches the specified value.
  • getAll(keys: IterableIterator<K> | K[]): ReadonlyMap<K, V>

    • Retrieves all values associated with the specified keys.
  • set(key: K, value: V): Promise<V | undefined>

    • Sets the value for the specified key.
  • setAll(entries: ReadonlyMap<K, V>): Promise<ReadonlyMap<K, V>>

    • Sets multiple entries in the map.
  • insert(key: K, value: V): Promise<V | undefined>

    • Inserts the specified entry into the map.
  • insertAll(entries: ReadonlyMap<K, V> | [K, V][]): Promise<ReadonlyMap<K, V>>

    • Inserts multiple entries into the map.
  • delete(key: K): Promise<boolean>

    • Deletes the entry associated with the specified key.
  • deleteAll(keys: ReadonlySet<K> | K[]): Promise<ReadonlySet<K>>

    • Deletes multiple entries from the map.
  • remove(key: K): Promise<boolean>

    • Removes the entry associated with the specified key.
  • removeAll(keys: ReadonlySet<K> | K[]): Promise<ReadonlyMap<K, V>>

    • Removes multiple entries from the map.
  • updateIf(key: K, value: V, oldValue: V): Promise<boolean>

    • Updates the entry if the current value matches the specified old value.
  • export(): HamokMapSnapshot

    • Exports the map data as a snapshot.
  • import(data: HamokMapSnapshot, eventing?: boolean): void

    • Imports data from a snapshot.
  • [Symbol.iterator](): IterableIterator<[K, V]>

    • Returns an iterator over the entries in the map.

Example Usage

const map = new HamokMap(connection, baseMap);

map.set("key", "value").then((oldValue) => {
  console.log(`Old value: ${oldValue}`);
});

const value = map.get("key");
console.log(`Value: ${value}`);

for (const [key, value] of map) {
  console.log(`Key: ${key}, Value: ${value}`);
}

map.close();

Examples

FAQ

How do I create a HamokMap instance?

To create a HamokMap instance, you need a Hamok instance. Here is an example:

const map = hamok.createMap<string, number>({
  mapId: "exampleMap",
});

How can I listen to HamokMap events?

You can listen to HamokMap events using the on method. Here is an example:

map.on("insert", (key, value) => console.log(`Inserted: ${key} -> ${value}`));
map.on("update", (key, oldValue, newValue) =>
  console.log(`Updated: ${key} from ${oldValue} to ${newValue}`)
);
map.on("remove", (key, value) => console.log(`Removed: ${key} -> ${value}`));
map.on("clear", () => console.log("Map cleared"));
map.on("close", () => console.log("Map closed"));

How do I close a HamokMap instance?

To close a HamokMap instance, use the close method:

map.close();

And what does that do?

The close method closes the map and releases any held resources. It deletes the map from the Hamok instance and stops all event emissions. You cannot mutate the map after it is closed.

How do I clear all entries in a HamokMap?

To clear all entries in a HamokMap, use the clear method:

await map.clear();

How do I retrieve a value for a given key?

To retrieve a value for a given key, use the get method:

const value = map.get("key1");
console.log(value);

How do I set a value for a given key?

To set a value for a given key, use the set method:

const oldValue = await map.set("key1", "value1");
console.log(oldValue);

How do I insert a value for a given key?

To insert a value for a given key, use the insert method:

const existingValue = await map.insert("key1", "value1");
console.log(
  existingValue
    ? "Insert failed, because the map already has a value for the key: " +
        existingValue
    : "Insert successful"
);

How do I delete an entry for a given key?

To delete an entry for a given key, use the delete method:

const success = await map.delete("key1");
console.log("Deleted", success ? "successfully" : "failed");

What is the difference between the set and insert methods?

The set method updates the value for a given key, regardless of whether the key already exists. The insert method, however, only adds a new key-value pair if the key does not already exist.

map.on("insert", (key, value) => console.log(`Inserted: ${key} -> ${value}`));
map.on("update", (key, oldValue, newValue) =>
  console.log(`Updated: ${key} from ${oldValue} to ${newValue}`)
);
await map.set("key", "value"); // Updates or inserts the key-value pair
await map.set("key", "new-value"); // Updates or inserts the key-value pair

What is the difference between delete and remove methods?

The delete method deletes the entry associated with the specified keyand returns true, or false indicating it’s success or failuire. The remove method removes the entry associated with the specified key return the removed value.

How many entries can be pushed as batch to setAll, insertAll, deleteAll, and removeAll methods?

As many as you wish, just take care of the memory usage. If you go in this way of large maps and batches, you should configure the maxOutboundMessageKeys and maxOutboundMessageValues options. In that way, you can control the maximum number of keys and values allowed in request or response messages preventing the communication channel to be bloated.

How do I retrieve multiple values for multiple keys?

To retrieve multiple values for multiple keys, use the getAll method:

const keys = ["key1", "key2"];
const values = map.getAll(keys);

console.log(values);

Should I export the map?

As you wish, but I designed the export and import methods to be used by Hamok to export and import the whole state of the map.

Can I change the value of entries in the map when iterating or modify the baseMap?

You can, but you should not! THe whole purpose of the HamokMap is to give a wrapper to mutate the baseMap in a safe way. If you use the method designed for mutating the baseMap and keep entries consistent then you have a consistent map. If you change the baseMap directly, you can break the consistency of the map. But noone stops you from doing that.