# Milestone Database Adapter

## Content

The **Milestone Database Adapter** improve the performance for frequent query historical snapshot by periodically saving document snapshots. Unlike the main database adapter ([IDatabaseAdapter](https://developer.mescius.com/spreadjs/api/collaboration/js-collaboration-ot/interfaces/IDatabaseAdapter#interface-idatabaseadapters-t)) only retains the latest snapshot, the Milestone Adapter([IMilestoneDatabaseAdapter](https://developer.mescius.com/spreadjs/api/collaboration/js-collaboration-ot/interfaces/IMilestoneDatabaseAdapter) ) stores multiple versions of snapshots, optimizing the performance of [fetchHistorySnapshot](https://developer.mescius.com/spreadjs/api/collaboration/js-collaboration-ot/classes/DocumentServices#fetchhistorysnapshot).
**Applicable Scenarios**: Applications that require quick access to document history
**Default Implementation**: Built-in memory-based adapter

## Interface: IMilestoneDatabaseAdapter

Developers need to implement these methods to support custom storage.

```typescript
/**
 * Defines the interface for a milestone database adapter.
 */
export interface IMilestoneDatabaseAdapter<S> {
    /**
     * The interval for saving milestone snapshots.
     * @default 1000
     */
    interval: number;
    /**
     * Saves a milestone snapshot.
     */
    saveMilestoneSnapshot(snapshot: ISnapshot<S>): Promise<boolean>;
    /**
     * Retrieves a milestone snapshot by document ID and version.
     */
    getMilestoneSnapshot(id: string, version: number): Promise<ISnapshot<S> | undefined>;
}
```

**Explanation of** `interval`:
It controls the frequency of milestone snapshot saves. For example, if `interval` is set to `1000`, a snapshot is saved every 1000 operations (`op`).

* A smaller interval increases storage overhead but improves historical query performance.
* A larger interval reduces storage needs but may increase the time required to reconstruct history.

## Default Implementation

The `js-collaboration-ot` library provides a built-in in-memory milestone adapter:

* **Description**: Data is stored in RAM and lost after a restart.
* **Purpose**: Development and testing.
* **Configuration**: Default `interval` is `1000`.

> type=warning
> The built-in adapter implementation is only suitable for development and testing environments. In production environments, please implement a custom adapter.

## Implement a Custom Adapter

You can implement the [IMilestoneDatabaseAdapter](https://developer.mescius.com/spreadjs/api/collaboration/js-collaboration-ot/interfaces/IMilestoneDatabaseAdapter) interface to create a custom adapter.
This is a simple example about in-Memory milestone adapter:

```typescript
import { IMilestoneDatabaseAdapter } from '@mescius/js-collaboration-ot';

// Custom milestone adapter
class CustomMilestoneDb implements IMilestoneDatabaseAdapter {
  constructor() {
    this.interval = 1000; // Default interval
    this.map = new Map(); // Store snapshot list
  }

  async saveMilestoneSnapshot(snapshot) {
    let list = this.map.get(snapshot.id) || [];
    list.push(snapshot);
    list.sort((a, b) => a.v - b.v); // Sort by version
    this.map.set(snapshot.id, list);
    return true;
  }

  async getMilestoneSnapshot(id, version) {
    const list = this.map.get(id) || [];
    let result;
    for (const snapshot of list) {
      if (snapshot.v <= version) {
        result = snapshot;
      } else {
        break;
      }
    }
    return result;
  }
}

const docService = new DocumentServices({
  db: new MemoryDb(),
  milestoneDb: new CustomMilestoneDb()
});
```

## Summary

The Milestone Database Adapter optimizes historical access performance by periodically saving snapshots. The built-in in-memory implementation is suitable for testing, while a custom adapter can meet production needs. After integrating the adapter into `DocumentServices`, you can significantly improve the efficiency of `fetchHistorySnapshot`, making it ideal for applications that frequently query historical data.