mirror of
https://github.com/gristlabs/grist-core.git
synced 2024-10-27 20:44:07 +00:00
(core) add explicit doc and inventory creation step
Summary: Currently, if a document is created by importing a file, inventory creation is a little haphazard - it works, but triggers a "surprise" message. This diff makes initialization of inventory explicit, so that surprise messages shouldn't happen during document creation. Test Plan: manual Reviewers: dsagal Reviewed By: dsagal Differential Revision: https://phab.getgrist.com/D2696
This commit is contained in:
parent
24e76b4abc
commit
d5b00f5169
@ -300,6 +300,7 @@ export class ActiveDoc extends EventEmitter {
|
|||||||
@ActiveDoc.keepDocOpen
|
@ActiveDoc.keepDocOpen
|
||||||
public async createDoc(docSession: OptDocSession): Promise<ActiveDoc> {
|
public async createDoc(docSession: OptDocSession): Promise<ActiveDoc> {
|
||||||
this.logDebug(docSession, "createDoc");
|
this.logDebug(docSession, "createDoc");
|
||||||
|
await this._docManager.storageManager.prepareToCreateDoc(this.docName);
|
||||||
await this.docStorage.createFile();
|
await this.docStorage.createFile();
|
||||||
await this._rawPyCall('load_empty');
|
await this._rawPyCall('load_empty');
|
||||||
const timezone = docSession.browserSettings ? docSession.browserSettings.timezone : DEFAULT_TIMEZONE;
|
const timezone = docSession.browserSettings ? docSession.browserSettings.timezone : DEFAULT_TIMEZONE;
|
||||||
|
@ -110,6 +110,17 @@ export class DocSnapshotInventory implements IInventory {
|
|||||||
constructor(private _doc: ExternalStorage, private _meta: ExternalStorage,
|
constructor(private _doc: ExternalStorage, private _meta: ExternalStorage,
|
||||||
private _getFilename: (key: string) => Promise<string>) {}
|
private _getFilename: (key: string) => Promise<string>) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Start keeping inventory for a new document.
|
||||||
|
*/
|
||||||
|
public async create(key: string) {
|
||||||
|
await this._mutex.runExclusive(key, async() => {
|
||||||
|
const fname = await this._getFilename(key);
|
||||||
|
await this._saveToFile(fname, []);
|
||||||
|
this._needFlush.add(key);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a new snapshot of a document to the existing inventory. A prevSnapshotId may
|
* Add a new snapshot of a document to the existing inventory. A prevSnapshotId may
|
||||||
* be supplied as a cross-check. It will be matched against the most recent
|
* be supplied as a cross-check. It will be matched against the most recent
|
||||||
@ -126,7 +137,7 @@ export class DocSnapshotInventory implements IInventory {
|
|||||||
await this._mutex.runExclusive(key, async() => {
|
await this._mutex.runExclusive(key, async() => {
|
||||||
const snapshots = await this._getSnapshots(key, prevSnapshotId);
|
const snapshots = await this._getSnapshots(key, prevSnapshotId);
|
||||||
// Could be already added if reconstruction happened.
|
// Could be already added if reconstruction happened.
|
||||||
if (snapshots[0].snapshotId === snapshot.snapshotId) { return; }
|
if (snapshots[0] && snapshots[0].snapshotId === snapshot.snapshotId) { return; }
|
||||||
this._normalizeMetadata(snapshot);
|
this._normalizeMetadata(snapshot);
|
||||||
snapshots.unshift(snapshot);
|
snapshots.unshift(snapshot);
|
||||||
const fname = await this._getFilename(key);
|
const fname = await this._getFilename(key);
|
||||||
|
@ -87,6 +87,10 @@ export class DocStorageManager implements IDocStorageManager {
|
|||||||
*/
|
*/
|
||||||
public async prepareLocalDoc(docName: string, docSession: OptDocSession): Promise<boolean> { return false; }
|
public async prepareLocalDoc(docName: string, docSession: OptDocSession): Promise<boolean> { return false; }
|
||||||
|
|
||||||
|
public async prepareToCreateDoc(docName: string): Promise<void> {
|
||||||
|
// nothing to do
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a promise for the list of docNames to show in the doc list. For the file-based
|
* Returns a promise for the list of docNames to show in the doc list. For the file-based
|
||||||
* storage, this will include all .grist files under the docsRoot.
|
* storage, this will include all .grist files under the docsRoot.
|
||||||
@ -212,7 +216,7 @@ export class DocStorageManager implements IDocStorageManager {
|
|||||||
// nothing to do
|
// nothing to do
|
||||||
}
|
}
|
||||||
|
|
||||||
public addToStorage(id: string): void {
|
public async addToStorage(id: string): Promise<void> {
|
||||||
// nothing to do
|
// nothing to do
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -184,7 +184,8 @@ export class HostedStorageManager implements IDocStorageManager {
|
|||||||
*/
|
*/
|
||||||
public async addToStorage(docId: string) {
|
public async addToStorage(docId: string) {
|
||||||
if (this._disableS3) { return; }
|
if (this._disableS3) { return; }
|
||||||
await this._ext.upload(docId, this.getPath(docId));
|
this._uploads.addOperation(docId);
|
||||||
|
await this._uploads.expediteOperationAndWait(docId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public getPath(docName: string): string {
|
public getPath(docName: string): string {
|
||||||
@ -234,6 +235,13 @@ export class HostedStorageManager implements IDocStorageManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async prepareToCreateDoc(docName: string): Promise<void> {
|
||||||
|
if (this._inventory) {
|
||||||
|
await this._inventory.create(docName);
|
||||||
|
this._onInventoryChange(docName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Gets a copy of the document, eg. for downloading. Returns full file path.
|
// Gets a copy of the document, eg. for downloading. Returns full file path.
|
||||||
// Copy won't change if edits are made to the document. It is caller's responsibility
|
// Copy won't change if edits are made to the document. It is caller's responsibility
|
||||||
// to delete the result.
|
// to delete the result.
|
||||||
@ -656,10 +664,7 @@ export class HostedStorageManager implements IDocStorageManager {
|
|||||||
metadata
|
metadata
|
||||||
}
|
}
|
||||||
await this._inventory.add(docId, snapshot, prevSnapshotId);
|
await this._inventory.add(docId, snapshot, prevSnapshotId);
|
||||||
const scheduled = this._pruner.requestPrune(docId);
|
await this._onInventoryChange(docId);
|
||||||
if (!scheduled) {
|
|
||||||
await this._inventory.flush(docId);
|
|
||||||
}
|
|
||||||
} finally {
|
} finally {
|
||||||
// Clean up backup.
|
// Clean up backup.
|
||||||
// NOTE: fse.remove succeeds also when the file does not exist.
|
// NOTE: fse.remove succeeds also when the file does not exist.
|
||||||
@ -667,6 +672,14 @@ export class HostedStorageManager implements IDocStorageManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Make sure inventory change is followed up on.
|
||||||
|
private async _onInventoryChange(docId: string) {
|
||||||
|
const scheduled = this._pruner.requestPrune(docId);
|
||||||
|
if (!scheduled) {
|
||||||
|
await this._inventory.flush(docId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Extract actionHash, actionNum, and timezone from a document backup.
|
// Extract actionHash, actionNum, and timezone from a document backup.
|
||||||
private async _getDocMetadata(fname: string): Promise<{[key: string]: string}> {
|
private async _getDocMetadata(fname: string): Promise<{[key: string]: string}> {
|
||||||
const result: Record<string, string> = {};
|
const result: Record<string, string> = {};
|
||||||
|
@ -12,6 +12,7 @@ export interface IDocStorageManager {
|
|||||||
// In the current implementation, it is called in the context of an
|
// In the current implementation, it is called in the context of an
|
||||||
// AsyncCreate[docName].
|
// AsyncCreate[docName].
|
||||||
prepareLocalDoc(docName: string, docSession: OptDocSession): Promise<boolean>;
|
prepareLocalDoc(docName: string, docSession: OptDocSession): Promise<boolean>;
|
||||||
|
prepareToCreateDoc(docName: string): Promise<void>;
|
||||||
|
|
||||||
listDocs(): Promise<DocEntry[]>;
|
listDocs(): Promise<DocEntry[]>;
|
||||||
deleteDoc(docName: string, deletePermanently?: boolean): Promise<void>;
|
deleteDoc(docName: string, deletePermanently?: boolean): Promise<void>;
|
||||||
@ -24,7 +25,7 @@ export interface IDocStorageManager {
|
|||||||
// If reason is set to 'edit' the user-facing timestamp on the document should be updated.
|
// If reason is set to 'edit' the user-facing timestamp on the document should be updated.
|
||||||
markAsChanged(docName: string, reason?: 'edit'): void;
|
markAsChanged(docName: string, reason?: 'edit'): void;
|
||||||
testReopenStorage(): void; // restart storage during tests
|
testReopenStorage(): void; // restart storage during tests
|
||||||
addToStorage(docName: string): void; // add a new local document to storage
|
addToStorage(docName: string): Promise<void>; // add a new local document to storage
|
||||||
prepareToCloseStorage(): void; // speed up sync with remote store
|
prepareToCloseStorage(): void; // speed up sync with remote store
|
||||||
getCopy(docName: string): Promise<string>; // get an immutable copy of a document
|
getCopy(docName: string): Promise<string>; // get an immutable copy of a document
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user