Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 50 additions & 0 deletions packages/@d-zero/google-sheets/src/sheets/sheet.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,15 @@ describe('appendRow / flush', () => {
expect(sheet.sentCount).toBe(3);
});

test('pendingCount returns to 0 after [Symbol.asyncDispose] flushes the buffer', async () => {
const { parent } = createRecordingParent();
const sheet = new Sheet(mockSheet as never, parent as never);

await sheet.appendRow(...Array.from({ length: 3 }, () => eagerRow()));
await sheet[Symbol.asyncDispose]();
expect(sheet.pendingCount).toBe(0);
});

test('suspends auto-flush as soon as a lazy row enters the buffer', async () => {
const { parent, updateCellsRows } = createRecordingParent();
const sheet = new Sheet(mockSheet as never, parent as never);
Expand Down Expand Up @@ -328,6 +337,47 @@ describe('appendRow / flush', () => {
expect(sheet.sentCount).toBe(0);
});

test('pendingCount reflects buffered rows below the auto-flush threshold', async () => {
const { parent } = createRecordingParent();
const sheet = new Sheet(mockSheet as never, parent as never);

expect(sheet.pendingCount).toBe(0);

await sheet.appendRow(...Array.from({ length: 2499 }, () => eagerRow()));
expect(sheet.pendingCount).toBe(2499);
});

test('pendingCount drops to the chunk remainder once auto-flush fires', async () => {
const { parent } = createRecordingParent();
const sheet = new Sheet(mockSheet as never, parent as never);

// 6000 rows -> two auto-flushed chunks of 2500, 1000 left buffered.
await sheet.appendRow(...Array.from({ length: 6000 }, () => eagerRow()));
expect(sheet.pendingCount).toBe(1000);
});

test('pendingCount returns to 0 after flush() drains the buffer', async () => {
const { parent } = createRecordingParent();
const sheet = new Sheet(mockSheet as never, parent as never);

await sheet.appendRow(...Array.from({ length: 6000 }, () => eagerRow()));
await sheet.flush();
expect(sheet.pendingCount).toBe(0);
});

test('pendingCount includes rows held past SEND_CHUNK_SIZE while a lazy row suspends auto-flush', async () => {
const { parent } = createRecordingParent();
const sheet = new Sheet(mockSheet as never, parent as never);

// 2499 eager (below threshold, no flush yet) + 1 lazy (latches
// auto-flush) + 5000 more eager = 7500 held in the buffer instead of
// auto-flushing at the 2500 boundary.
await sheet.appendRow(...Array.from({ length: 2499 }, () => eagerRow()));
await sheet.appendRow(lazyRow());
await sheet.appendRow(...Array.from({ length: 5000 }, () => eagerRow()));
expect(sheet.pendingCount).toBe(7500);
});

test('detects a lazy cell at any column position, not just the first cell of the row', async () => {
// containsLazyCell() iterates every cell of the row. A defensive
// "optimization" that only checks row[0] would slip past unit tests
Expand Down
22 changes: 22 additions & 0 deletions packages/@d-zero/google-sheets/src/sheets/sheet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,28 @@ export class Sheet {
return props;
}

/**
* バッファに溜まっているが未送信の行数。`SEND_CHUNK_SIZE` 未満で
* 自動 flush の閾値に達していない行、または遅延セルによって自動
* flush が保留されている行を指す。
*
* `flush()` 呼び出し前に「これから何行分のネットワーク往復が
* 発生するか」を呼び出し元が表示する用途(例: 進捗表示の
* "flushing N rows..." メッセージ)。`onProgress` は chunk の
* `batchUpdate` 完了後にしか呼ばれないため、送信開始前の見積もりは
* この getter でのみ得られる。
* @example
* ```ts
* if (sheet.pendingCount > 0) {
* showProgress(`flushing ${sheet.pendingCount} rows...`);
* }
* await sheet.flush();
* ```
*/
get pendingCount() {
return this.#pendingRows.length;
}

/**
* `appendRow()` / `flush()` を通じてこれまでに送信した累計行数。
* 進捗表示用途。`setHeaders()` の送信分は含まない。
Expand Down
Loading