HA-store API Documentation
A high-availability data-fetching wrapper with smart coalescing, batching, and TLRU caching for optimal performance.
Reduces database load through intelligent request coalescing and batching. TLRU caching optimized for Zipfian distribution patterns. Battle-tested and lightweight.
Installation
npm install ha-store
Quick Start
Basic setup with a resolver function:
import haStore from 'ha-store';
const store = haStore({
resolver: async (ids, params) => {
// Fetch your data
const results = await db.users.find({
_id: { $in: ids }
});
return results;
},
tick: 50,
max: 100,
cache: {
ttl: 60000,
size: 1000
}
});
// Fetch single item
const user = await store.get('user-123');
// Fetch multiple items
const users = await store.getMany(['user-1', 'user-2', 'user-3']);
Coalescing
Detects duplicate requests and reuses the original Promise handle instead of making redundant calls.
When multiple identical requests are made simultaneously, HA-store recognizes duplicates and returns the same Promise to all callers, reducing load on your data source.
Batching
Buffers incoming requests for a set duration and bundles them together before sending to the data source.
Configuration
- tick: Time interval between batches (in milliseconds)
- max: Maximum number of records per batch
const store = haStore({
resolver: myResolver,
tick: 50, // Wait 50ms
max: 100 // Up to 100 items per batch
});
Caching
Uses Time-aware Least Recently Used (TLRU) caching strategy, optimized for data following Zipfian distribution patterns.
Only frequently-accessed "hot" data benefits from caching. HA-store automatically manages cache based on access patterns, keeping your most-requested items instantly available.
Constructor
Creates a new HA-store instance with the provided configuration.
Parameters
| Name | Type | Description |
|---|---|---|
config |
Object | Configuration object |
Example
const store = haStore({
resolver: async (ids, params) => {
return await database.findByIds(ids, params);
},
tick: 50,
max: 100
});
get()
Fetches a single item by ID with automatic coalescing, batching, and caching.
Parameters
| Name | Type | Default | Description |
|---|---|---|---|
id |
string | - | Unique identifier |
params |
object | {} | Context parameters passed to resolver |
agg |
function | null | Aggregation function |
Example
const user = await store.get('user-123');
const user = await store.get('user-123', { includeProfile: true });
getMany()
Fetches multiple items by their IDs. Returns an object mapping each ID to its result.
Parameters
| Name | Type | Default | Description |
|---|---|---|---|
ids |
string[] | - | Array of unique identifiers |
params |
object | {} | Context parameters |
agg |
function | null | Aggregation function |
Example
const users = await store.getMany(['user-1', 'user-2', 'user-3']);
// Result format (uses Promise.allSettled):
// {
// 'user-1': { status: 'fulfilled', value: {...} },
// 'user-2': { status: 'fulfilled', value: {...} },
// 'user-3': { status: 'rejected', reason: Error(...) }
// }
set()
Manually sets items in the cache. Useful for cache warming or updating cached values.
Parameters
| Name | Type | Description |
|---|---|---|
items |
any[] | Array of items to cache |
ids |
string[] | Array of IDs (required) |
params |
object | Context parameters |
Example
await store.set(
[{ name: 'Alice' }, { name: 'Bob' }],
['user-1', 'user-2']
);
clear()
Clears items from the cache.
Example
// Clear single item
await store.clear('user-123');
// Clear multiple items
await store.clear(['user-1', 'user-2', 'user-3']);
size()
Returns statistics about the current store state.
Example
const stats = await store.size();
console.log(stats);
// {
// records: 150,
// queue: { ... }
// }
Configuration Options
| Option | Type | Default | Description |
|---|---|---|---|
resolver |
function | - | Data fetching function |
tick |
number | 50 | Batching interval (ms) |
max |
number | 100 | Max items per batch |
delimiter |
string | '|' | Key delimiter |
cache |
object | - | Cache configuration |
Cache Configuration
| Option | Type | Description |
|---|---|---|
ttl |
number | Time-to-live (ms) |
size |
number | Maximum cached items |
store |
string | object | 'inMemory' or 'redis' |
Example
const store = haStore({
resolver: myResolver,
cache: {
ttl: 60000,
size: 1000,
store: 'inMemory'
}
});
Cache Stores
In-Memory Store
Default cache store that keeps data in application memory.
import haStore, { caches } from 'ha-store';
const store = haStore({
resolver: myResolver,
cache: {
store: caches.inMemory
}
});
Redis Store
Distributed cache store using Redis.
import haStore, { caches } from 'ha-store';
const store = haStore({
resolver: myResolver,
cache: {
store: caches.redis,
redis: {
host: 'localhost',
port: 6379
}
}
});
Resolvers
PostgreSQL Resolver
import haStore, { resolvers } from 'ha-store';
const store = haStore({
resolver: resolvers.postgres({
connection: {
host: 'localhost',
database: 'mydb'
},
table: 'users',
idColumn: 'id'
})
});
Custom Resolver
const customResolver = async (ids, params, agg) => {
const results = await fetchFromAPI(ids, params);
return results;
};
const store = haStore({
resolver: customResolver
});
Events
The store instance extends EventEmitter and emits events for monitoring:
store.on('cache-hit', (data) => {
console.log('Cache hit:', data);
});
store.on('cache-miss', (data) => {
console.log('Cache miss:', data);
});
store.on('batch-sent', (data) => {
console.log('Batch sent:', data);
});
store.on('error', (error) => {
console.error('Error:', error);
});