@syncular/server 0.31.0 → 0.32.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +124 -74
- package/dist/admin.d.ts +394 -50
- package/dist/admin.js +714 -82
- package/dist/d1-storage.d.ts +6 -5
- package/dist/d1-storage.js +136 -21
- package/dist/events-ring.d.ts +12 -2
- package/dist/events-ring.js +27 -2
- package/dist/events.d.ts +21 -3
- package/dist/handler.js +36 -13
- package/dist/operations.js +4 -4
- package/dist/postgres-storage.d.ts +6 -5
- package/dist/postgres-storage.js +102 -18
- package/dist/push.js +28 -7
- package/dist/realtime.d.ts +15 -0
- package/dist/realtime.js +46 -7
- package/dist/seed.js +4 -3
- package/dist/sqlite-storage.d.ts +6 -5
- package/dist/sqlite-storage.js +115 -18
- package/dist/storage.d.ts +58 -7
- package/package.json +2 -2
- package/src/admin.ts +1215 -120
- package/src/d1-storage.ts +199 -25
- package/src/events-ring.ts +31 -2
- package/src/events.ts +27 -4
- package/src/handler.ts +47 -16
- package/src/operations.ts +8 -4
- package/src/postgres-storage.ts +173 -28
- package/src/push.ts +40 -9
- package/src/realtime.ts +60 -7
- package/src/seed.ts +4 -3
- package/src/sqlite-storage.ts +181 -26
- package/src/storage.ts +72 -9
package/src/sqlite-storage.ts
CHANGED
|
@@ -30,11 +30,18 @@ import {
|
|
|
30
30
|
layoutsOf,
|
|
31
31
|
migratePayload,
|
|
32
32
|
parseLayouts,
|
|
33
|
+
quoteIdent,
|
|
33
34
|
retiredTableNames,
|
|
34
35
|
rewritePlan,
|
|
35
36
|
rewriteRowSql,
|
|
36
37
|
rewriteValues,
|
|
37
38
|
SCHEMA_META_DDL_SQLITE,
|
|
39
|
+
SYNC_COLUMN_VERSIONS_COLUMN,
|
|
40
|
+
SYNC_PARTITION_COLUMN,
|
|
41
|
+
SYNC_PAYLOAD_COLUMN,
|
|
42
|
+
SYNC_ROW_ID_COLUMN,
|
|
43
|
+
SYNC_SCOPES_COLUMN,
|
|
44
|
+
SYNC_VERSION_COLUMN,
|
|
38
45
|
type StoredColumnLayout,
|
|
39
46
|
scanRowPageSql,
|
|
40
47
|
schemaDdl,
|
|
@@ -51,9 +58,11 @@ import {
|
|
|
51
58
|
deserializePushResult,
|
|
52
59
|
placeholders,
|
|
53
60
|
SQLITE_DDL,
|
|
61
|
+
type SqliteChangeRecord,
|
|
54
62
|
type SqliteCommitWindowRecord,
|
|
55
63
|
type SqliteRowRecord,
|
|
56
64
|
serializePushResult,
|
|
65
|
+
toStoredChange,
|
|
57
66
|
toStoredRow,
|
|
58
67
|
} from './sqlite-dialect';
|
|
59
68
|
import {
|
|
@@ -66,8 +75,11 @@ import type {
|
|
|
66
75
|
AuthoritativeQueryValue,
|
|
67
76
|
CheckpointDeclaration,
|
|
68
77
|
ClientCursorInfo,
|
|
78
|
+
ClientPushResult,
|
|
69
79
|
ClientRecord,
|
|
70
80
|
ClientSubscription,
|
|
81
|
+
CommitChangeSummary,
|
|
82
|
+
CommitDetail,
|
|
71
83
|
CommitMetadata,
|
|
72
84
|
CommitMetadataQuery,
|
|
73
85
|
CommitWindowQuery,
|
|
@@ -82,6 +94,9 @@ import type {
|
|
|
82
94
|
ReactionFailureUpdate,
|
|
83
95
|
ReactionListQuery,
|
|
84
96
|
ReactionPruneQuery,
|
|
97
|
+
RowChangeRecord,
|
|
98
|
+
RowChangesQuery,
|
|
99
|
+
RowListQuery,
|
|
85
100
|
RowScanQuery,
|
|
86
101
|
ScopeActivityQuery,
|
|
87
102
|
ScopeCommitActivity,
|
|
@@ -1949,7 +1964,11 @@ END`);
|
|
|
1949
1964
|
partition: string,
|
|
1950
1965
|
query: CommitMetadataQuery,
|
|
1951
1966
|
): Promise<CommitMetadata[]> {
|
|
1952
|
-
// Newest-first window, resumed by `afterSeq` (exclusive lower bound)
|
|
1967
|
+
// Newest-first window, resumed by `afterSeq` (exclusive lower bound) and
|
|
1968
|
+
// ended by `beforeSeq` (exclusive upper bound) when paging older. An
|
|
1969
|
+
// omitted bound is the largest safe commitSeq, so one statement serves
|
|
1970
|
+
// both the bounded and unbounded read.
|
|
1971
|
+
const beforeSeq = query.beforeSeq ?? Number.MAX_SAFE_INTEGER;
|
|
1953
1972
|
const rows = query.table
|
|
1954
1973
|
? this.db
|
|
1955
1974
|
.query<
|
|
@@ -1960,16 +1979,16 @@ END`);
|
|
|
1960
1979
|
actor_id: string;
|
|
1961
1980
|
created_at_ms: number;
|
|
1962
1981
|
},
|
|
1963
|
-
[string, number, string, number]
|
|
1982
|
+
[string, number, number, string, number]
|
|
1964
1983
|
>(
|
|
1965
1984
|
`SELECT c.commit_seq, c.client_id, c.client_commit_id, c.actor_id, c.created_at_ms
|
|
1966
1985
|
FROM sync_commits c
|
|
1967
|
-
WHERE c.partition=? AND c.commit_seq>?
|
|
1986
|
+
WHERE c.partition=? AND c.commit_seq>? AND c.commit_seq<?
|
|
1968
1987
|
AND EXISTS (SELECT 1 FROM sync_changes ch
|
|
1969
1988
|
WHERE ch.partition=c.partition AND ch.commit_seq=c.commit_seq AND ch.tbl=?)
|
|
1970
1989
|
ORDER BY c.commit_seq DESC LIMIT ?`,
|
|
1971
1990
|
)
|
|
1972
|
-
.all(partition, query.afterSeq, query.table, query.limit)
|
|
1991
|
+
.all(partition, query.afterSeq, beforeSeq, query.table, query.limit)
|
|
1973
1992
|
: this.db
|
|
1974
1993
|
.query<
|
|
1975
1994
|
{
|
|
@@ -1979,14 +1998,45 @@ END`);
|
|
|
1979
1998
|
actor_id: string;
|
|
1980
1999
|
created_at_ms: number;
|
|
1981
2000
|
},
|
|
1982
|
-
[string, number, number]
|
|
2001
|
+
[string, number, number, number]
|
|
1983
2002
|
>(
|
|
1984
2003
|
`SELECT commit_seq, client_id, client_commit_id, actor_id, created_at_ms
|
|
1985
2004
|
FROM sync_commits
|
|
1986
|
-
WHERE partition=? AND commit_seq>?
|
|
2005
|
+
WHERE partition=? AND commit_seq>? AND commit_seq<?
|
|
1987
2006
|
ORDER BY commit_seq DESC LIMIT ?`,
|
|
1988
2007
|
)
|
|
1989
|
-
.all(partition, query.afterSeq, query.limit);
|
|
2008
|
+
.all(partition, query.afterSeq, beforeSeq, query.limit);
|
|
2009
|
+
// `changeSample`: one extra statement for the whole page — the first
|
|
2010
|
+
// `sample` changes (change-index order) of every listed commit.
|
|
2011
|
+
const sampleCount =
|
|
2012
|
+
query.changeSample !== undefined &&
|
|
2013
|
+
Number.isInteger(query.changeSample) &&
|
|
2014
|
+
query.changeSample > 0
|
|
2015
|
+
? query.changeSample
|
|
2016
|
+
: 0;
|
|
2017
|
+
const samples = new Map<number, CommitChangeSummary[]>();
|
|
2018
|
+
if (sampleCount > 0 && rows.length > 0) {
|
|
2019
|
+
const seqs = rows.map((row) => row.commit_seq);
|
|
2020
|
+
const records = this.db
|
|
2021
|
+
.query<
|
|
2022
|
+
{ commit_seq: number; tbl: string; row_id: string; op: number },
|
|
2023
|
+
(string | number)[]
|
|
2024
|
+
>(
|
|
2025
|
+
`SELECT commit_seq, tbl, row_id, op FROM sync_changes
|
|
2026
|
+
WHERE partition=? AND commit_seq IN (${placeholders(seqs.length)}) AND idx<?
|
|
2027
|
+
ORDER BY commit_seq, idx`,
|
|
2028
|
+
)
|
|
2029
|
+
.all(partition, ...seqs, sampleCount);
|
|
2030
|
+
for (const record of records) {
|
|
2031
|
+
const sample = samples.get(record.commit_seq) ?? [];
|
|
2032
|
+
sample.push({
|
|
2033
|
+
table: record.tbl,
|
|
2034
|
+
rowId: record.row_id,
|
|
2035
|
+
op: record.op === 1 ? 'upsert' : 'delete',
|
|
2036
|
+
});
|
|
2037
|
+
samples.set(record.commit_seq, sample);
|
|
2038
|
+
}
|
|
2039
|
+
}
|
|
1990
2040
|
return rows.map((row) => {
|
|
1991
2041
|
const changes = this.db
|
|
1992
2042
|
.query<{ tbl: string; n: number }, [string, number]>(
|
|
@@ -2001,10 +2051,134 @@ END`);
|
|
|
2001
2051
|
createdAtMs: row.created_at_ms,
|
|
2002
2052
|
changeCount: changes.reduce((sum, c) => sum + c.n, 0),
|
|
2003
2053
|
tables: changes.map((c) => c.tbl),
|
|
2054
|
+
...(sampleCount > 0
|
|
2055
|
+
? { sample: samples.get(row.commit_seq) ?? [] }
|
|
2056
|
+
: {}),
|
|
2004
2057
|
};
|
|
2005
2058
|
});
|
|
2006
2059
|
}
|
|
2007
2060
|
|
|
2061
|
+
async getCommit(
|
|
2062
|
+
partition: string,
|
|
2063
|
+
commitSeq: number,
|
|
2064
|
+
): Promise<CommitDetail | undefined> {
|
|
2065
|
+
const meta = this.db
|
|
2066
|
+
.query<
|
|
2067
|
+
{
|
|
2068
|
+
client_id: string;
|
|
2069
|
+
client_commit_id: string;
|
|
2070
|
+
actor_id: string;
|
|
2071
|
+
created_at_ms: number;
|
|
2072
|
+
},
|
|
2073
|
+
[string, number]
|
|
2074
|
+
>(
|
|
2075
|
+
'SELECT client_id, client_commit_id, actor_id, created_at_ms FROM sync_commits WHERE partition=? AND commit_seq=?',
|
|
2076
|
+
)
|
|
2077
|
+
.get(partition, commitSeq);
|
|
2078
|
+
if (meta === null) return undefined;
|
|
2079
|
+
const changes = this.db
|
|
2080
|
+
.query<SqliteChangeRecord, [string, number]>(
|
|
2081
|
+
'SELECT tbl, row_id, op, row_version, scopes, payload FROM sync_changes WHERE partition=? AND commit_seq=? ORDER BY idx',
|
|
2082
|
+
)
|
|
2083
|
+
.all(partition, commitSeq)
|
|
2084
|
+
.map(toStoredChange);
|
|
2085
|
+
return {
|
|
2086
|
+
commitSeq,
|
|
2087
|
+
clientId: meta.client_id,
|
|
2088
|
+
clientCommitId: meta.client_commit_id,
|
|
2089
|
+
actorId: meta.actor_id,
|
|
2090
|
+
createdAtMs: meta.created_at_ms,
|
|
2091
|
+
changeCount: changes.length,
|
|
2092
|
+
tables: [...new Set(changes.map((change) => change.table))].sort(),
|
|
2093
|
+
changes,
|
|
2094
|
+
};
|
|
2095
|
+
}
|
|
2096
|
+
|
|
2097
|
+
async listRowChanges(
|
|
2098
|
+
partition: string,
|
|
2099
|
+
query: RowChangesQuery,
|
|
2100
|
+
): Promise<RowChangeRecord[]> {
|
|
2101
|
+
// Retained-log read for one row: no dedicated index (the write path pays
|
|
2102
|
+
// nothing for it), bounded by retention (§4.6).
|
|
2103
|
+
return this.db
|
|
2104
|
+
.query<
|
|
2105
|
+
{
|
|
2106
|
+
commit_seq: number;
|
|
2107
|
+
op: number;
|
|
2108
|
+
row_version: number | null;
|
|
2109
|
+
actor_id: string;
|
|
2110
|
+
client_id: string;
|
|
2111
|
+
created_at_ms: number;
|
|
2112
|
+
},
|
|
2113
|
+
[string, string, string, number]
|
|
2114
|
+
>(
|
|
2115
|
+
`SELECT ch.commit_seq, ch.op, ch.row_version, c.actor_id, c.client_id, c.created_at_ms
|
|
2116
|
+
FROM sync_changes ch
|
|
2117
|
+
JOIN sync_commits c
|
|
2118
|
+
ON c.partition=ch.partition AND c.commit_seq=ch.commit_seq
|
|
2119
|
+
WHERE ch.partition=? AND ch.tbl=? AND ch.row_id=?
|
|
2120
|
+
ORDER BY ch.commit_seq DESC, ch.idx DESC LIMIT ?`,
|
|
2121
|
+
)
|
|
2122
|
+
.all(partition, query.table, query.rowId, query.limit)
|
|
2123
|
+
.map((row) => ({
|
|
2124
|
+
commitSeq: row.commit_seq,
|
|
2125
|
+
op: row.op === 1 ? 'upsert' : 'delete',
|
|
2126
|
+
...(row.row_version !== null ? { rowVersion: row.row_version } : {}),
|
|
2127
|
+
actorId: row.actor_id,
|
|
2128
|
+
clientId: row.client_id,
|
|
2129
|
+
createdAtMs: row.created_at_ms,
|
|
2130
|
+
}));
|
|
2131
|
+
}
|
|
2132
|
+
|
|
2133
|
+
async listRows(partition: string, query: RowListQuery): Promise<StoredRow[]> {
|
|
2134
|
+
// Keyset page over the row table's (partition, rowId) primary key: an
|
|
2135
|
+
// index range read, no scope filter, no per-row lookup.
|
|
2136
|
+
return this.db
|
|
2137
|
+
.query<SqliteRowRecord, [string, string, number]>(
|
|
2138
|
+
`SELECT ${quoteIdent(SYNC_ROW_ID_COLUMN)} AS row_id, ${quoteIdent(SYNC_VERSION_COLUMN)} AS server_version, ${quoteIdent(SYNC_SCOPES_COLUMN)} AS scopes, ${quoteIdent(SYNC_PAYLOAD_COLUMN)} AS payload, ${quoteIdent(SYNC_COLUMN_VERSIONS_COLUMN)} AS column_versions
|
|
2139
|
+
FROM ${quoteIdent(this.table(query.table).name)}
|
|
2140
|
+
WHERE ${quoteIdent(SYNC_PARTITION_COLUMN)}=? AND ${quoteIdent(SYNC_ROW_ID_COLUMN)}>?
|
|
2141
|
+
ORDER BY ${quoteIdent(SYNC_ROW_ID_COLUMN)} LIMIT ?`,
|
|
2142
|
+
)
|
|
2143
|
+
.all(partition, query.afterRowId ?? '', query.limit)
|
|
2144
|
+
.map(toStoredRow);
|
|
2145
|
+
}
|
|
2146
|
+
|
|
2147
|
+
async countRows(partition: string, table: string): Promise<number> {
|
|
2148
|
+
const record = this.db
|
|
2149
|
+
.query<{ n: number }, [string]>(
|
|
2150
|
+
`SELECT count(*) AS n FROM ${quoteIdent(this.table(table).name)} WHERE ${quoteIdent(SYNC_PARTITION_COLUMN)}=?`,
|
|
2151
|
+
)
|
|
2152
|
+
.get(partition);
|
|
2153
|
+
return record?.n ?? 0;
|
|
2154
|
+
}
|
|
2155
|
+
|
|
2156
|
+
async listPushResults(
|
|
2157
|
+
partition: string,
|
|
2158
|
+
clientCommitId: string,
|
|
2159
|
+
): Promise<ClientPushResult[]> {
|
|
2160
|
+
// Retained outcomes for one clientCommitId: no dedicated index, ordered
|
|
2161
|
+
// by client so the read is deterministic.
|
|
2162
|
+
return this.db
|
|
2163
|
+
.query<{ client_id: string; result: string }, [string, string]>(
|
|
2164
|
+
'SELECT client_id, result FROM sync_push_results WHERE partition=? AND client_commit_id=? ORDER BY client_id',
|
|
2165
|
+
)
|
|
2166
|
+
.all(partition, clientCommitId)
|
|
2167
|
+
.map((record) => {
|
|
2168
|
+
try {
|
|
2169
|
+
return {
|
|
2170
|
+
clientId: record.client_id,
|
|
2171
|
+
result: deserializePushResult(record.result),
|
|
2172
|
+
};
|
|
2173
|
+
} catch {
|
|
2174
|
+
throw syncError(
|
|
2175
|
+
'sync.idempotency_cache_miss',
|
|
2176
|
+
'persisted push result unreadable (§6.3)',
|
|
2177
|
+
);
|
|
2178
|
+
}
|
|
2179
|
+
});
|
|
2180
|
+
}
|
|
2181
|
+
|
|
2008
2182
|
async scopeActivity(
|
|
2009
2183
|
partition: string,
|
|
2010
2184
|
query: ScopeActivityQuery,
|
|
@@ -2044,25 +2218,6 @@ END`);
|
|
|
2044
2218
|
return out;
|
|
2045
2219
|
}
|
|
2046
2220
|
|
|
2047
|
-
async getRowScopes(
|
|
2048
|
-
partition: string,
|
|
2049
|
-
table: string,
|
|
2050
|
-
rowId: string,
|
|
2051
|
-
): Promise<
|
|
2052
|
-
{ serverVersion: number; scopes: Record<string, string> } | undefined
|
|
2053
|
-
> {
|
|
2054
|
-
const record = this.db
|
|
2055
|
-
.query<{ server_version: number; scopes: string }, [string, string]>(
|
|
2056
|
-
selectRowScopesSql(this.table(table), 'sqlite'),
|
|
2057
|
-
)
|
|
2058
|
-
.get(partition, rowId);
|
|
2059
|
-
if (record === null) return undefined;
|
|
2060
|
-
return {
|
|
2061
|
-
serverVersion: record.server_version,
|
|
2062
|
-
scopes: JSON.parse(record.scopes) as Record<string, string>,
|
|
2063
|
-
};
|
|
2064
|
-
}
|
|
2065
|
-
|
|
2066
2221
|
async listPartitions(): Promise<string[]> {
|
|
2067
2222
|
return (await this.listPartitionRegistry()).map((entry) => entry.partition);
|
|
2068
2223
|
}
|
package/src/storage.ts
CHANGED
|
@@ -379,14 +379,62 @@ export interface CommitMetadata {
|
|
|
379
379
|
readonly createdAtMs: number;
|
|
380
380
|
readonly changeCount: number;
|
|
381
381
|
readonly tables: readonly string[];
|
|
382
|
+
/** The first `changeSample` changes in commit order, when requested. */
|
|
383
|
+
readonly sample?: readonly CommitChangeSummary[];
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
/** One change without its payload, for commit lists. */
|
|
387
|
+
export interface CommitChangeSummary {
|
|
388
|
+
readonly table: string;
|
|
389
|
+
readonly rowId: string;
|
|
390
|
+
readonly op: 'upsert' | 'delete';
|
|
382
391
|
}
|
|
383
392
|
|
|
384
393
|
export interface CommitMetadataQuery {
|
|
385
|
-
/** Window `afterSeq < commitSeq
|
|
394
|
+
/** Window lower bound, exclusive: `afterSeq < commitSeq`. */
|
|
386
395
|
readonly afterSeq: number;
|
|
396
|
+
/** Window upper bound, exclusive: `commitSeq < beforeSeq` (older pages). */
|
|
397
|
+
readonly beforeSeq?: number;
|
|
398
|
+
/** Newest first, at most `limit` commits. */
|
|
387
399
|
readonly limit: number;
|
|
388
400
|
/** Restrict to commits that touched this table (via the change index). */
|
|
389
401
|
readonly table?: string;
|
|
402
|
+
/** Attach the first N changes of each commit as `sample`. */
|
|
403
|
+
readonly changeSample?: number;
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
export interface RowListQuery {
|
|
407
|
+
readonly table: string;
|
|
408
|
+
/** Resume after this rowId (exclusive); `null` = start of table. */
|
|
409
|
+
readonly afterRowId: string | null;
|
|
410
|
+
readonly limit: number;
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
/** A stored push outcome with the client that sent it. */
|
|
414
|
+
export interface ClientPushResult {
|
|
415
|
+
readonly clientId: string;
|
|
416
|
+
readonly result: StoredPushResult;
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
/** One retained commit with its changes, for the admin commit drill-down. */
|
|
420
|
+
export interface CommitDetail extends CommitMetadata {
|
|
421
|
+
readonly changes: readonly StoredChange[];
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
/** One retained change to a single row, for the admin row history. */
|
|
425
|
+
export interface RowChangeRecord {
|
|
426
|
+
readonly commitSeq: number;
|
|
427
|
+
readonly op: 'upsert' | 'delete';
|
|
428
|
+
readonly rowVersion?: number;
|
|
429
|
+
readonly actorId: string;
|
|
430
|
+
readonly clientId: string;
|
|
431
|
+
readonly createdAtMs: number;
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
export interface RowChangesQuery {
|
|
435
|
+
readonly table: string;
|
|
436
|
+
readonly rowId: string;
|
|
437
|
+
readonly limit: number;
|
|
390
438
|
}
|
|
391
439
|
|
|
392
440
|
/** One recent commit touching a scope key, for the admin scope activity view. */
|
|
@@ -921,8 +969,16 @@ export interface ServerStorage {
|
|
|
921
969
|
* touched tables), the newest-oriented window an operator inspects.
|
|
922
970
|
* `scopeActivity`: the recent commits touching one scope key, via the
|
|
923
971
|
* change scope index (never a log scan).
|
|
924
|
-
* `
|
|
925
|
-
*
|
|
972
|
+
* `getCommit`: one retained commit with its changes and payloads;
|
|
973
|
+
* `undefined` when the commit does not exist or was pruned.
|
|
974
|
+
* `listRowChanges`: the retained changes to one row, newest first. It
|
|
975
|
+
* reads the partition's retained log without a dedicated index, so the
|
|
976
|
+
* write path pays nothing for it and its cost is bounded by retention.
|
|
977
|
+
* `listRows`: one table's rows ordered by rowId, without a scope filter.
|
|
978
|
+
* `countRows`: one table's row count.
|
|
979
|
+
* `listPushResults`: every stored idempotency outcome for one
|
|
980
|
+
* clientCommitId across the partition's clients, scanning the retained
|
|
981
|
+
* outcomes without a dedicated index.
|
|
926
982
|
* `listPartitions`: the partition-only compatibility view of
|
|
927
983
|
* `listPartitionRegistry`, sorted.
|
|
928
984
|
*/
|
|
@@ -935,13 +991,20 @@ export interface ServerStorage {
|
|
|
935
991
|
partition: string,
|
|
936
992
|
query: ScopeActivityQuery,
|
|
937
993
|
): Promise<ScopeCommitActivity[]>;
|
|
938
|
-
|
|
994
|
+
getCommit?(
|
|
939
995
|
partition: string,
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
996
|
+
commitSeq: number,
|
|
997
|
+
): Promise<CommitDetail | undefined>;
|
|
998
|
+
listRowChanges?(
|
|
999
|
+
partition: string,
|
|
1000
|
+
query: RowChangesQuery,
|
|
1001
|
+
): Promise<RowChangeRecord[]>;
|
|
1002
|
+
listRows?(partition: string, query: RowListQuery): Promise<StoredRow[]>;
|
|
1003
|
+
countRows?(partition: string, table: string): Promise<number>;
|
|
1004
|
+
listPushResults?(
|
|
1005
|
+
partition: string,
|
|
1006
|
+
clientCommitId: string,
|
|
1007
|
+
): Promise<ClientPushResult[]>;
|
|
945
1008
|
listPartitions(): Promise<string[]>;
|
|
946
1009
|
}
|
|
947
1010
|
|