Help us shape the future of Go! Take the 2026 Go Developer Survey

store

package
v1.0.0 Latest Latest
Warning

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

Go to latest
Published: Sep 23, 2026 License: Apache-2.0 Imports: 8 Imported by: 0

README

Store JavaScript API Documentation

The Store JavaScript API provides a unified interface for key-value storage with MongoDB-style list operations in Yao applications. This API supports LRU cache, Redis, MongoDB, and Xun (database-backed) backends through a consistent JavaScript interface.

Table of Contents

Installation & Setup

The Store API is automatically available in Yao JavaScript runtime. No additional installation is required.

// Create a store instance
const store = new Store("cache_name");

TypeScript Integration

For TypeScript development, you can define the Store interface:

interface YaoStore {
  // Key-Value Operations
  Set(key: string, value: any, ttl?: number): void;
  Get(key: string): any;
  GetSet(key: string, getValue: (key: string) => any, ttl?: number): any;
  GetDel(key: string): any;
  Has(key: string): boolean;
  Del(key: string): void;
  Keys(): string[];
  Len(): number;
  Clear(): void;

  // Batch Operations
  SetMulti(values: { [key: string]: any }, ttl?: number): void;
  GetMulti(keys: string[]): { [key: string]: any };
  DelMulti(keys: string[]): void;
  GetSetMulti(
    keys: string[],
    getValue: (key: string) => any,
    ttl?: number
  ): { [key: string]: any };

  // List Operations
  Push(key: string, ...values: any[]): void;
  Pop(key: string, position: number): any;
  Pull(key: string, value: any): void;
  PullAll(key: string, ...values: any[]): void;
  AddToSet(key: string, ...values: any[]): void;
  ArrayLen(key: string): number;
  ArrayGet(key: string, index: number): any;
  ArraySet(key: string, index: number, value: any): void;
  ArraySlice(key: string, skip: number, limit: number): any[];
  ArrayPage(key: string, page: number, pageSize: number): any[];
  ArrayAll(key: string): any[];
}

declare const Store: {
  new (name: string): YaoStore;
};

// Usage in TypeScript
const store: YaoStore = new Store("my_cache");

API Reference

Key-Value Operations
Set(key, value, ttl?)

Set a key-value pair with optional TTL (Time To Live) in seconds.

store.Set("user:123", { name: "John", age: 30 });
store.Set("session:abc", "active", 3600); // Expires in 1 hour
Get(key)

Get a value by key. Returns undefined if key doesn't exist.

const user = store.Get("user:123");
if (user) {
  console.log(user.name); // "John"
}
GetSet(key, getValue, ttl?)

Get a value or set it if it doesn't exist (cache-aside pattern).

const userData = store.GetSet(
  "user:123",
  (key: string) => {
    // This function is called only if the key doesn't exist
    return fetchUserFromDatabase(key);
  },
  3600
);
GetDel(key)

Get a value and delete it atomically.

const token = store.GetDel("temp:token:abc");
Has(key)

Check if a key exists.

if (store.Has("user:123")) {
  console.log("User exists in cache");
}
Del(key)

Delete a key.

store.Del("user:123");
Keys()

Get all keys in the store.

const allKeys: string[] = store.Keys();
console.log("Total keys:", allKeys.length);
Len()

Get the total number of keys.

const count: number = store.Len();
Clear()

Remove all keys from the store.

store.Clear();
Batch Operations
SetMulti(values, ttl?)

Set multiple key-value pairs at once.

const values = {
  "user:123": { name: "John", age: 30 },
  "user:456": { name: "Jane", age: 25 },
  "config:theme": "dark",
};
store.SetMulti(values, 3600); // Set all with 1 hour TTL
GetMulti(keys)

Get multiple values at once.

const keys = ["user:123", "user:456", "config:theme"];
const values = store.GetMulti(keys);
console.log(values); // { "user:123": {...}, "user:456": {...}, "config:theme": "dark" }
DelMulti(keys)

Delete multiple keys at once.

const keys = ["user:123", "user:456", "temp:data"];
store.DelMulti(keys);
GetSetMulti(keys, getValue, ttl?)

Get multiple values or set them if they don't exist.

const keys = ["user:123", "user:456"];
const values = store.GetSetMulti(
  keys,
  (key: string) => {
    return fetchUserFromDatabase(key);
  },
  3600
);
List Operations
Push(key, ...values)

Add elements to the end of a list.

store.Push("fruits", "apple", "banana", "cherry");
store.Push("numbers", 1, 2, 3, 4, 5);
Pop(key, position)

Remove and return an element from a list.

// Pop from end (position = 1)
const lastItem = store.Pop("fruits", 1);

// Pop from beginning (position = -1)
const firstItem = store.Pop("fruits", -1);
Pull(key, value)

Remove all occurrences of a specific value.

store.Pull("fruits", "apple"); // Removes all "apple" entries
PullAll(key, ...values)

Remove all occurrences of multiple values.

store.PullAll("fruits", "apple", "banana", "cherry");
AddToSet(key, ...values)

Add elements only if they don't already exist (ensures uniqueness).

store.AddToSet("tags", "javascript", "typescript", "javascript");
// Only unique values are added
ArrayLen(key)

Get the length of a list.

const count: number = store.ArrayLen("fruits");
ArrayGet(key, index)

Get an element at a specific index.

const firstFruit = store.ArrayGet("fruits", 0);
const lastFruit = store.ArrayGet("fruits", -1); // If supported
ArraySet(key, index, value)

Set an element at a specific index.

store.ArraySet("fruits", 1, "orange"); // Replace element at index 1
ArrayAll(key)

Get all elements in a list.

const allFruits: any[] = store.ArrayAll("fruits");
ArraySlice(key, skip, limit)

Get a slice of elements with skip and limit.

// Skip 5 elements, return next 10
const slice: any[] = store.ArraySlice("items", 5, 10);
ArrayPage(key, page, pageSize)

Get a specific page of elements (page starts from 1).

// Get page 1 with 10 items per page
const page1: any[] = store.ArrayPage("items", 1, 10);

// Get page 2 with 10 items per page
const page2: any[] = store.ArrayPage("items", 2, 10);

Usage Examples

Basic Key-Value Usage
// User session management
function manageUserSession(userId: string, sessionData: any) {
  const store = new Store("sessions");

  // Set session with 1 hour expiry
  store.Set(`user:${userId}`, sessionData, 3600);

  // Check if user is logged in
  if (store.Has(`user:${userId}`)) {
    console.log("User is active");
  }

  // Get session data
  const session = store.Get(`user:${userId}`);
  return session;
}
Shopping Cart Implementation
function ShoppingCart(userId: string) {
  const store = new Store("shopping_carts");
  const key = `cart:${userId}`;

  return {
    addItem(productId: string, quantity: number = 1) {
      for (let i = 0; i < quantity; i++) {
        store.Push(key, productId);
      }
    },

    removeItem(productId: string) {
      store.Pull(key, productId);
    },

    getItems(): string[] {
      return store.ArrayAll(key) || [];
    },

    getItemCount(): number {
      return store.ArrayLen(key);
    },

    clear() {
      store.Del(key);
    },

    getPage(page: number, pageSize: number = 10): string[] {
      return store.ArrayPage(key, page, pageSize);
    },
  };
}

// Usage
const cart = ShoppingCart("user123");
cart.addItem("product456", 2);
cart.addItem("product789");
console.log("Items:", cart.getItems());
console.log("Total items:", cart.getItemCount());
Tag Management System
function TagManager(entityType: string) {
  const store = new Store("tags");

  return {
    addTags(entityId: string, ...tags: string[]) {
      const key = `${entityType}:${entityId}:tags`;
      store.AddToSet(key, ...tags); // Ensures uniqueness
    },

    removeTags(entityId: string, ...tags: string[]) {
      const key = `${entityType}:${entityId}:tags`;
      store.PullAll(key, ...tags);
    },

    getTags(entityId: string): string[] {
      const key = `${entityType}:${entityId}:tags`;
      return store.ArrayAll(key) || [];
    },

    hasTag(entityId: string, tag: string): boolean {
      const tags = this.getTags(entityId);
      return tags.includes(tag);
    },
  };
}

// Usage
const articleTags = TagManager("article");
articleTags.addTags("123", "javascript", "typescript", "programming");
articleTags.addTags("123", "javascript"); // Won't create duplicate
console.log("Tags:", articleTags.getTags("123"));
Activity Feed with Pagination
function ActivityFeed(userId: string) {
  const store = new Store("activity_feeds");
  const key = `feed:${userId}`;

  return {
    addActivity(activity: any) {
      // Add timestamp
      const timestampedActivity = {
        ...activity,
        timestamp: Date.now(),
      };
      store.Push(key, timestampedActivity);

      // Keep only latest 1000 activities
      const total = store.ArrayLen(key);
      if (total > 1000) {
        // Remove oldest activities
        const excess = total - 1000;
        for (let i = 0; i < excess; i++) {
          store.Pop(key, -1); // Pop from beginning
        }
      }
    },

    getActivities(page: number = 1, pageSize: number = 20): any[] {
      return store.ArrayPage(key, page, pageSize);
    },

    getLatest(count: number = 10): any[] {
      return store.ArraySlice(key, 0, count);
    },

    getTotalCount(): number {
      return store.ArrayLen(key);
    },
  };
}

// Usage
const feed = ActivityFeed("user123");
feed.addActivity({ type: "login", message: "User logged in" });
feed.addActivity({ type: "post", message: "Created new post" });

const recentActivities = feed.getLatest(5);
const page1 = feed.getActivities(1, 10);
Caching with GetSet Pattern
interface User {
  id: string;
  name: string;
  email: string;
}

function UserService() {
  const store = new Store("users");

  return {
    getUser(userId: string): User | null {
      return store.GetSet(
        `user:${userId}`,
        (key: string) => {
          // This function is called only if cache miss
          console.log(`Fetching user ${userId} from database...`);
          return fetchUserFromDatabase(userId);
        },
        3600 // Cache for 1 hour
      );
    },

    updateUser(user: User) {
      // Update database first
      updateUserInDatabase(user);

      // Update cache
      store.Set(`user:${user.id}`, user, 3600);
    },

    deleteUser(userId: string) {
      // Delete from database
      deleteUserFromDatabase(userId);

      // Remove from cache
      store.Del(`user:${userId}`);
    },
  };
}

Error Handling

function safeStoreOperation() {
  const store = new Store("my_cache");

  try {
    // Operations that might fail
    const value = store.ArrayGet("list", 100); // Index might be out of range
    const popped = store.Pop("empty_list", 1); // List might be empty

    return value;
  } catch (error) {
    console.error("Store operation failed:", error);
    return null;
  }
}

Best Practices

1. Use Meaningful Key Names
// Good
store.Set("user:session:123", sessionData);
store.Push("notifications:user:456", notification);

// Avoid
store.Set("u123", sessionData);
store.Push("n", notification);
2. Set Appropriate TTL
// Short-lived data
store.Set("temp:token", token, 300); // 5 minutes

// Session data
store.Set("session:user", session, 3600); // 1 hour

// Long-term cache
store.Set("user:profile", profile, 86400); // 24 hours
3. Handle Cache Misses Gracefully
function getDataWithFallback(key: string) {
  const cached = store.Get(key);
  if (cached !== undefined) {
    return cached;
  }

  // Fallback to database or API
  const fresh = fetchFromSource(key);
  store.Set(key, fresh, 3600);
  return fresh;
}
4. Use Lists for Ordered Data
// Recent searches (ordered by time)
store.Push("recent_searches:user123", searchQuery);

// Keep only last 10 searches
if (store.ArrayLen("recent_searches:user123") > 10) {
  store.Pop("recent_searches:user123", -1); // Remove oldest
}
5. Use AddToSet for Unique Collections
// User interests (no duplicates)
store.AddToSet("interests:user123", "programming", "music", "travel");

// Tags (unique)
store.AddToSet("article:tags:456", "javascript", "tutorial", "beginner");
6. Implement Pagination for Large Lists
function getPaginatedResults(key: string, page: number, pageSize: number = 20) {
  const total = store.ArrayLen(key);
  const totalPages = Math.ceil(total / pageSize);
  const items = store.ArrayPage(key, page, pageSize);

  return {
    items,
    pagination: {
      page,
      pageSize,
      total,
      totalPages,
      hasNext: page < totalPages,
      hasPrev: page > 1,
    },
  };
}

Performance Considerations

  • LRU Cache: Fastest for frequent access, limited by memory
  • Redis: Good for distributed applications, network latency considerations
  • MongoDB: Best for complex queries and very large datasets
  • Xun: Database-backed storage with LRU cache layer, leverages existing database infrastructure

Choose the appropriate backend based on your application's requirements and configure the store accordingly in your Yao application.

Xun Store Features

The Xun store provides database-backed persistence with performance optimization:

  • LRU Cache Layer: Fast reads from in-memory cache
  • Async Persistence: Batch writes to reduce database load (configurable interval)
  • Lazy Loading: Data loaded from database on first access
  • TTL Support: Automatic expiration with background cleanup
  • Multi-Database: Supports MySQL, PostgreSQL, SQLite via Xun connectors

Note: Up to persist_interval seconds of data may be lost on application crash.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Store

type Store struct{}

Store Javascript API

func New

func New() *Store

New create a new Store object

func (*Store) ExportFunction

func (store *Store) ExportFunction(iso *v8go.Isolate) *v8go.FunctionTemplate

ExportFunction Export as a javascript Cache function

func (*Store) ExportObject

func (store *Store) ExportObject(iso *v8go.Isolate) *v8go.ObjectTemplate

ExportObject Export as a Cache Object

Jump to

Keyboard shortcuts

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