@convex-dev/geospatial
Version:
A geospatial index for Convex
101 lines • 3.33 kB
JavaScript
import * as approximateCounter from "../lib/approximateCounter.js";
import { encodeBound } from "../lib/tupleKey.js";
export class DatabaseRange {
ctx;
logger;
cursor;
interval;
prefetchSize;
stats;
state = { type: "init" };
constructor(ctx, logger, cursor, interval, prefetchSize, stats) {
this.ctx = ctx;
this.logger = logger;
this.cursor = cursor;
this.interval = interval;
this.prefetchSize = prefetchSize;
this.stats = stats;
}
async current() {
if (this.state.type === "done") {
return null;
}
if (this.state.type === "buffered") {
return this.state.buffer[this.state.pos];
}
const buffer = await this.initialQuery();
this.stats.queriesIssued++;
this.stats.rowsRead += buffer.length;
if (buffer.length === 0) {
this.state = { type: "done" };
return null;
}
this.state = { type: "buffered", buffer, pos: 0 };
return this.state.buffer[0];
}
async advance() {
if (this.state.type === "done") {
return null;
}
if (this.state.type === "init") {
await this.current();
return await this.advance();
}
if (this.state.pos < this.state.buffer.length - 1) {
this.state.pos++;
return this.state.buffer[this.state.pos];
}
const lastKey = this.state.buffer[this.state.buffer.length - 1];
const buffer = await this.advanceQuery(lastKey);
this.stats.queriesIssued++;
this.stats.rowsRead += buffer.length;
if (buffer.length === 0) {
this.state = { type: "done" };
return null;
}
this.state = { type: "buffered", buffer, pos: 0 };
return this.state.buffer[0];
}
async seek(tuple) {
if (this.state.type === "init") {
await this.current();
return await this.seek(tuple);
}
if (this.state.type === "done") {
return;
}
if (tuple < this.state.buffer[0]) {
return;
}
if (tuple <= this.state.buffer[this.state.buffer.length - 1]) {
const newPos = this.state.buffer.findIndex((key) => key >= tuple);
this.state.pos = Math.max(newPos, this.state.pos);
return;
}
const buffer = await this.seekQuery(tuple);
this.stats.queriesIssued++;
this.stats.rowsRead += buffer.length;
if (buffer.length === 0) {
this.state = { type: "done" };
return;
}
this.state = { type: "buffered", buffer, pos: 0 };
}
async sizeHint() {
const count = await approximateCounter.estimateCount(this.ctx, this.getCounterKey());
this.logger.debug(`Size hint for ${this.getCounterKey()} is ${count}`);
return count;
}
setPrefetch(prefetch) {
this.prefetchSize = prefetch;
}
applyInterval(q) {
let withEnd = q;
if (this.interval.endExclusive !== undefined) {
const bound = encodeBound(this.interval.endExclusive);
withEnd = q.lt("tupleKey", bound);
}
return withEnd;
}
}
//# sourceMappingURL=databaseRange.js.map