hamok
Version:
Lightweight Distributed Object Storage on RAFT consensus algorithm
207 lines (156 loc) • 7.17 kB
Markdown
## User Manual
[Hamok](./index.md) / [HamokEmitter](./emitter.md) / [HamokMap](./map.md) / [HamokQueue](./queue.md) / HamokRecord / [HamokRemoteMap](./remoteMap.md)
## Table of Contents
- [Overview](#overview)
- [Configuration](#configuration)
- [API Reference](#api-reference)
- [Properties](#properties)
- [Events](#events)
- [Methods](#methods)
- [Examples](#examples)
- [FAQ](#faq)
## Overview
The `HamokRecord` class is designed to manage replicated storage with event-driven notifications. It supports operations like insertion, updating, deletion, and clearing of records, while emitting corresponding events.
### Create a HamokEmitter instance
You need a `Hamok` to create a `HamokRecord` instance. Here is how you can create a `HamokRecord` instance:
```typescript
const queue = hamok.createRecord<{ foo: string; bar: number }>({
recordId: "exampleRecord",
});
```
## Configuration
You can pass the following configuration options at the time of creating a `HamokRecord`:
```typescript
const record = hamok.createRecord<{ foo: string; bar: number }>({
/**
* The unique identifier for the record.
*/
recordId: "record1",
/**
* 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 function to determine equality between two values.
* Used for custom equality checking.
*/
equalValues: (a: V, b: V) => a === b,
/**
* Optional. The codec for encoding and decoding payloads.
*/
payloadsCodec: new Map([["foo", myCodec]]),
/**
* Optional. The initial object for the record.
*/
initialObject: { foo: "value1", bar: 42 },
});
```
## API Reference
### `HamokRecord<T extends HamokRecordObject>` Class
A class for managing distributed records with event-driven capabilities.
#### Properties
- **`id`**: `string` - The unique identifier of the record.
- **`closed`**: `boolean` - Indicates whether the record is closed.
- **`connection`**: `HamokConnection<string, string>` - The connection used by the record.
- **`equalValues`**: `<K extends keyof T>(a: T[K], b: T[K]) => boolean` - A function to compare values for equality.
#### Methods
- **close**(): `void` - Closes the record and releases any held resources.
- **clear**(): `Promise<void>` - Clears the record.
- **get**<`K extends keyof T`>(`key: K`): `T[K] | undefined` - Retrieves the value associated with the given key.
- **set**<`K extends keyof T`>(`key: K`, `value: T[K]`): `Promise<T[K] | undefined>` - Sets the value for the given key.
- **insert**<`K extends keyof T`>(`key: K`, `value: T[K]`): `Promise<T[K] | undefined>` - Inserts a new value for the given key.
- **updateIf**<`K extends keyof T`>(`key: K`, `value: T[K]`, `oldValue: T[K]`): `Promise<boolean>` - Updates the value if the old value matches.
- **delete**<`K extends keyof T`>(`key: K`): `Promise<boolean>` - Deletes the value associated with the given key.
- **export**(): `HamokRecordSnapshot` - Exports the current state of the record.
- **import**(`data: HamokRecordSnapshot`, `eventing?: boolean`): `void` - Imports the state from a snapshot.
#### Events
- **`clear`**: Emitted when the record is cleared.
- **`remove`**: Emitted when an entry is removed.
- **`insert`**: Emitted when an entry is inserted.
- **`update`**: Emitted when an entry is updated.
- **`close`**: Emitted when the record is closed.
### Example Usage
```typescript
const record = new HamokRecord<MyRecordType>(connection, {
equalValues: (a, b) => a === b,
payloadsCodec: new Map([["key1", myCodec]]),
initalObject: { key1: "value1" },
});
record.on("insert", (payload) => console.log("Inserted:", payload));
record.on("update", (payload) => console.log("Updated:", payload));
record.on("remove", (payload) => console.log("Removed:", payload));
record.on("clear", () => console.log("Cleared all entries"));
record.on("close", () => console.log("Record closed"));
await record.set("key2", "value2");
await record.updateIf("key2", "newValue2", "value2");
await record.delete("key2");
await record.clear();
record.close();
```
## Examples
- [use events](https://github.com/balazskreith/hamok-ts/blob/main/examples/src/record-events-example.ts)
- [use insert and get](https://github.com/balazskreith/hamok-ts/blob/main/examples/src/record-insert-get-example.ts)
- [record catchup](https://github.com/balazskreith/hamok-ts/blob/main/examples/src/record-dynamic-creating-example.ts)
## FAQ
### What is the difference between the `insert` and `set` 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.
```typescript
await record.set("key", "value"); // Updates or inserts the key-value pair
await record.insert("key", "value"); // Inserts only if the key does not exist
```
### How does the `updateIf` method work?
The `updateIf` method updates the value for a given key only if the current value matches the specified old value. This is useful for ensuring atomic updates based on the current state of the record.
```typescript
const success = await record.updateIf("key", "newValue", "currentValue");
if (success) {
console.log("Value updated successfully");
} else {
console.log("Value update failed");
}
```
### How can I check if the `HamokRecord` instance is closed?
You can check if the `HamokRecord` instance is closed by using the `closed` property.
```typescript
if (record.closed) {
console.log("The record is closed");
}
```
### What happens if I try to perform operations on a closed `HamokRecord`?
Performing operations on a closed `HamokRecord` will throw an error. Ensure that the record is not closed before performing any operations.
```typescript
if (!record.closed) {
await record.set("key", "value");
} else {
console.log("Cannot perform operations on a closed record");
}
```
### How can I listen for events on the `HamokRecord`?
You can listen for events on the `HamokRecord` by using the `on` method to register event listeners.
```typescript
record.on("insert", (payload) => console.log("Inserted:", payload));
record.on("update", (payload) => console.log("Updated:", payload));
record.on("remove", (payload) => console.log("Removed:", payload));
record.on("clear", () => console.log("Cleared all entries"));
record.on("close", () => console.log("Record closed"));
```
This documentation provides an overview of the `HamokRecord` class, its methods, properties, events, and common usage patterns. For more detailed examples and use cases, refer to the respective sections in the documentation.