Skip to content

Commit

Permalink
PouchDB snapshot implementation (#18)
Browse files Browse the repository at this point in the history
  • Loading branch information
vbabich authored May 11, 2021
1 parent 069a6af commit 86a4e46
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 22 deletions.
40 changes: 18 additions & 22 deletions packages/code-studio/src/console/command-history/CommandHistory.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -156,30 +156,23 @@ class CommandHistory extends Component {
* If they're not within the current viewport, will fetch them from the table
* @returns {Promise<string[]>} Array of selected commands
*/
getSelectedCommands() {
async getSelectedCommands() {
const { items, offset, selectedRanges } = this.state;
const ranges = selectedRanges.slice().sort((a, b) => a[0] - b[0]);

return this.pending.add(
new Promise((resolve, reject) => {
if (ranges.length === 0) {
resolve([]);
} else if (
ranges[0][0] >= offset &&
ranges[ranges.length - 1][1] < offset + items.length
) {
// All ranges are in the current viewport, just copy the data we've already got
resolve(
CommandHistory.getCommandsFromViewport(items, offset, ranges)
);
} else {
// TODO: core#376 Allow copying outside of current viewport
reject(
new Error('Unable to copy commands outside of current viewport')
);
}
})
);
if (ranges.length === 0) {
return [];
}
if (
ranges[0][0] >= offset &&
ranges[ranges.length - 1][1] < offset + items.length
) {
// All ranges are in the current viewport, just copy the data we've already got
return CommandHistory.getCommandsFromViewport(items, offset, ranges);
}
const { table } = this.props;
const snapshot = await this.pending.add(table.getSnapshot(ranges));
return [...snapshot.added].map(index => snapshot.get(index)?.name ?? '');
}

/**
Expand Down Expand Up @@ -353,7 +346,10 @@ CommandHistory.propTypes = {
language: PropTypes.string.isRequired,
sendToConsole: PropTypes.func.isRequired,
sendToNotebook: PropTypes.func.isRequired,
table: PropTypes.shape({ size: PropTypes.number }).isRequired,
table: PropTypes.shape({
size: PropTypes.number,
getSnapshot: PropTypes.func.isRequired,
}).isRequired,
};

export default CommandHistory;
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
StorageTableListener,
StorageItemSuccessErrorListener,
StorageItemSuccessListener,
StorageSnapshot,
} from './StorageTable';

const log = Log.module('PouchStorageTable');
Expand Down Expand Up @@ -252,6 +253,58 @@ export class PouchStorageTable<T extends StorageItem = StorageItem>

return item;
}

async getSnapshot(
sortedRanges: [number, number][]
): Promise<StorageSnapshot<T>> {
if (!this.currentViewport) {
throw new Error('Viewport not set');
}
const { currentViewport: viewport } = this;

const itemMap: Map<number, T> = new Map();
const indexes: number[] = [];
let lastIndex = -1;

await Promise.all(
sortedRanges.map(async ([from, to]) => {
const limit = to - from + 1;
return this.db
.find({
selector: selectorWithSearch(viewport.search),
skip: from,
limit,
sort: this.sort,
fields: ['id', 'name'],
})
.then(findSnapshotResult => {
for (let i = 0; i < limit; i += 1) {
const index = from + i;
indexes.push(index);
itemMap.set(index, findSnapshotResult.docs[i]);
}
});
})
);

function iterator() {
return {
hasNext: () => lastIndex + 1 < indexes.length,
next: () => {
lastIndex += 1;
return {
value: indexes[lastIndex],
done: lastIndex >= indexes.length,
};
},
};
}

return {
added: { [Symbol.iterator]: iterator },
get: (index: number) => itemMap.get(index),
};
}
}

export default PouchStorageTable;
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,11 @@ export type StorageTableListener = () => void;

export type StorageListenerRemover = () => void;

export type StorageSnapshot<T> = {
added: Iterable<number>;
get(index: number): T | undefined;
};

/**
* A table for getting a list of items from storage, with id/name pairs
* Can search the table with a case insensitive search
Expand All @@ -57,6 +62,7 @@ export interface StorageTable<T extends StorageItem = StorageItem> {
id: string,
listener: StorageItemListener<T>
): StorageListenerRemover;
getSnapshot(sortedRanges: [number, number][]): Promise<StorageSnapshot<T>>;
close(): void;
}

Expand Down

0 comments on commit 86a4e46

Please sign in to comment.