gristlabs_grist-core/app/common/DocSnapshot.ts
Alex Hall 4408315f2e (core) Add AzureExternalStorage
Summary:
Adds a new implementation of the interface ExternalStorage that works for Azure Blob Storage as an alternative to S3, for a specific self-hosting case.

Tweaks HostedStorageManager and ICreate to allow configuring different core implementations of ExternalStorage.

Followup tasks:

- Make this code available to self hosters, possibly by making it open source.
- Add an env var or other config option to specify the preferred type of storage. Currently using the var `AZURE_STORAGE_CONNECTION_STRING` to know how to connect to Azure when requested, but that choice still only lives in test code.

Test Plan: Generalized HostedStorageManager and ExternalStorage tests to test the new AzureExternalStorage alongside S3ExternalStorage. The HostedStorageManager tests also now test the 'cached' in-memory test storage in a way that's closer to the real storage methods.

Reviewers: paulfitz

Reviewed By: paulfitz

Differential Revision: https://phab.getgrist.com/D3413
2022-05-09 21:44:57 +02:00

70 lines
1.9 KiB
TypeScript

/**
* Core metadata about a single document version.
*/
export interface ObjSnapshot {
lastModified: string;
snapshotId: string;
}
/**
* Extended Grist metadata about a single document version. Names of fields are kept
* short since there is a tight limit on total metadata size in S3.
*/
export interface ObjMetadata {
t?: string; // timestamp
tz?: string; // timezone
h?: string; // actionHash
n?: number; // actionNum
label?: string;
}
export interface ObjSnapshotWithMetadata extends ObjSnapshot {
metadata?: ObjMetadata;
}
/**
* Information about a single document snapshot in S3, including a Grist docId.
*/
export interface DocSnapshot extends ObjSnapshotWithMetadata {
docId: string;
}
/**
* A collection of document snapshots. Most recent snapshots first.
*/
export interface DocSnapshots {
snapshots: DocSnapshot[];
}
/**
* Metadata format for external storage like S3 and Azure.
* The only difference is that external metadata values must be strings.
*
* For S3, there are restrictions on total length of metadata (2 KB).
* See: https://docs.aws.amazon.com/AmazonS3/latest/dev/UsingMetadata.html#UserMetadata
*/
type ExternalMetadata = Record<string, string>;
/**
* Convert metadata from internal Grist format to external storage format (string values).
*/
export function toExternalMetadata(metadata: ObjMetadata): ExternalMetadata {
const result: ExternalMetadata = {};
for (const [key, val] of Object.entries(metadata)) {
if (val !== undefined) { result[key] = String(val); }
}
return result;
}
/**
* Select metadata controlled by Grist, and convert to expected formats.
*/
export function toGristMetadata(metadata: ExternalMetadata): ObjMetadata {
const result: ObjMetadata = {};
for (const key of ['t', 'tz', 'h', 'label'] as const) {
if (metadata[key]) { result[key] = metadata[key]; }
}
if (metadata.n) { result.n = parseInt(metadata.n, 10); }
return result;
}