Skip to content

Commit

Permalink
Merge branch 'main' of https://github.com/0xOlias/ponder
Browse files Browse the repository at this point in the history
  • Loading branch information
kyscott18 committed Oct 3, 2024
2 parents 8aa736f + 649c862 commit 6ca983b
Show file tree
Hide file tree
Showing 11 changed files with 111 additions and 17 deletions.
2 changes: 1 addition & 1 deletion .github/actions/setup/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ runs:
- name: Set up foundry
uses: foundry-rs/foundry-toolchain@v1
with:
version: nightly
version: "nightly-d75318c9c7a1c6af5404fe96f63ca890dcdd588d"

- name: Install dependencies
shell: bash
Expand Down
21 changes: 21 additions & 0 deletions packages/core/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,26 @@
# @ponder/core

## 0.6.6

### Patch Changes

- [#1130](https://github.com/ponder-sh/ponder/pull/1130) [`a50db23dda44c32289c661d8799a37c5c6a88ec4`](https://github.com/ponder-sh/ponder/commit/a50db23dda44c32289c661d8799a37c5c6a88ec4) Thanks [@kyscott18](https://github.com/kyscott18)! - Fixed a bug introduced in `0.6.0` that caused some apps to log progress greater than 100% and re-sync blocks unnecessarily.

## 0.6.5

### Patch Changes

- [#1126](https://github.com/ponder-sh/ponder/pull/1126) [`0a3adb000d60e091b24a6e8facce194c41712fc6`](https://github.com/ponder-sh/ponder/commit/0a3adb000d60e091b24a6e8facce194c41712fc6) Thanks [@kyscott18](https://github.com/kyscott18)! - Fixed a bug introduced in v0.6 where extra transaction may be added to the database in the "realtime" sync when using factory contracts.

Any users that were affected by this bug and want to reduce the database size can do so with the query:

```sql
DELETE FROM ponder_sync.transactions WHERE
hash NOT IN (SELECT "transactionHash" FROM ponder_sync.logs)
AND
hash NOT IN (SELECT "transactionHash" FROM ponder_sync."callTraces");
```

## 0.6.4

### Patch Changes
Expand Down
2 changes: 1 addition & 1 deletion packages/core/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@ponder/core",
"version": "0.6.4",
"version": "0.6.6",
"description": "An open-source framework for crypto application backends",
"license": "MIT",
"type": "module",
Expand Down
46 changes: 38 additions & 8 deletions packages/core/src/common/telemetry.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,8 @@ import { mkdirSync } from "node:fs";
import os from "node:os";
import path from "node:path";
import { createTelemetry } from "@/common/telemetry.js";
import { wait } from "@/utils/wait.js";
import { rimrafSync } from "rimraf";
import { beforeEach, expect, test, vi } from "vitest";
import { afterEach, beforeEach, expect, test, vi } from "vitest";
import type { Common } from "./common.js";
import { createLogger } from "./logger.js";

Expand All @@ -14,7 +13,10 @@ const fetchSpy = vi.fn();
beforeEach(() => {
fetchSpy.mockReset();
vi.stubGlobal("fetch", fetchSpy);
return () => vi.unstubAllGlobals();
});

afterEach(() => {
vi.unstubAllGlobals();
});

beforeEach((context) => {
Expand Down Expand Up @@ -46,7 +48,7 @@ test("telemetry calls fetch with event body", async (context) => {
properties: { duration_seconds: process.uptime() },
});

await wait(0);
await telemetry.flush();
await telemetry.kill();

expect(fetchSpy).toHaveBeenCalledTimes(1);
Expand Down Expand Up @@ -77,10 +79,10 @@ test("telemetry does not submit events if telemetry is disabled", async (context
properties: { duration_seconds: process.uptime() },
});

await wait(0);
await telemetry.flush();
await telemetry.kill();

expect(fetchSpy).toHaveBeenCalledTimes(0);
expect(fetchSpy).not.toHaveBeenCalled();
});

test("telemetry throws if event is submitted after kill", async (context) => {
Expand All @@ -96,7 +98,7 @@ test("telemetry throws if event is submitted after kill", async (context) => {
});
}

await wait(0);
await telemetry.flush();
await telemetry.kill();

expect(fetchSpy).toHaveBeenCalledTimes(5);
Expand All @@ -106,7 +108,35 @@ test("telemetry throws if event is submitted after kill", async (context) => {
properties: { duration_seconds: process.uptime() },
});

await wait(100);
await telemetry.flush();

expect(fetchSpy).toHaveBeenCalledTimes(5);
});

test("kill resolves within 1 second even with slow events", async (context) => {
const telemetry = createTelemetry({
options: context.common.options,
logger: context.common.logger,
});

// Mock fetch to simulate a slow request
fetchSpy.mockImplementation(
() => new Promise((resolve) => setTimeout(resolve, 5000)),
);

// Record an event that will trigger the slow fetch
telemetry.record({
name: "lifecycle:heartbeat_send",
properties: { duration_seconds: process.uptime() },
});

const startTime = Date.now();
await telemetry.kill();
const endTime = Date.now();

const killDuration = endTime - startTime;
expect(killDuration).toBeLessThan(1100); // Allow a small buffer for execution time

// Ensure that fetch was called, but not completed
expect(fetchSpy).toHaveBeenCalledTimes(1);
});
13 changes: 11 additions & 2 deletions packages/core/src/common/telemetry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,11 @@ export function createTelemetry({
logger,
}: { options: Options; logger: Logger }) {
if (options.telemetryDisabled) {
return { record: (_event: TelemetryEvent) => {}, kill: async () => {} };
return {
record: (_event: TelemetryEvent) => {},
flush: async () => {},
kill: async () => {},
};
}

const conf = new Conf<DeviceConf>({
Expand Down Expand Up @@ -208,6 +212,11 @@ export function createTelemetry({
});
}, HEARTBEAT_INTERVAL_MS);

// Note that this method is only used for testing.
const flush = async () => {
await queue.onIdle();
};

const kill = async () => {
clearInterval(heartbeatInterval);
isKilled = true;
Expand All @@ -217,7 +226,7 @@ export function createTelemetry({
await Promise.race([queue.onIdle(), wait(1_000)]);
};

return { record, kill };
return { record, flush, kill };
}

async function getPackageManager() {
Expand Down
14 changes: 14 additions & 0 deletions packages/core/src/sync-realtime/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,20 @@ export const createRealtimeSync = (
return isMatched;
});

// Remove transactions and transaction receipts that may have been filtered out
const transactionHashes = new Set<Hash>();
for (const log of logs) {
transactionHashes.add(log.transactionHash);
}
for (const trace of callTraces) {
transactionHashes.add(trace.transactionHash);
}

transactions = transactions.filter((t) => transactionHashes.has(t.hash));
transactionReceipts = transactionReceipts.filter((t) =>
transactionHashes.has(t.transactionHash),
);

// Record matched block filters
for (const filter of blockFilters) {
if (isBlockFilterMatched({ filter, block })) {
Expand Down
18 changes: 15 additions & 3 deletions packages/core/src/sync/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -997,8 +997,20 @@ export async function* localHistoricalSyncGenerator({
// Cursor to track progress.
let fromBlock = hexToNumber(syncProgress.start.number);

// Handle a cache hit by fast forwarding and potentially exiting
if (syncProgress.cached !== undefined) {
/**
* Handle a cache hit by fast forwarding and potentially exiting.
* A cache hit can either be: (listed by priority)
* 1) recovering progress from earlier invocations with different `finalized` blocks
* 2) recovering progress from the interval cache
*/
if (
syncProgress.current !== undefined &&
(syncProgress.cached === undefined ||
hexToNumber(syncProgress.current.number) >
hexToNumber(syncProgress.cached.number))
) {
fromBlock = hexToNumber(syncProgress.current.number) + 1;
} else if (syncProgress.cached !== undefined) {
// `getEvents` can make progress without calling `sync`, so immediately "yield"
yield;

Expand Down Expand Up @@ -1026,7 +1038,7 @@ export async function* localHistoricalSyncGenerator({
* time spent syncing ≈ time before indexing function feedback.
*/
const interval: Interval = [
fromBlock,
Math.min(fromBlock, hexToNumber(historicalLast.number)),
Math.min(fromBlock + estimateRange, hexToNumber(historicalLast.number)),
];

Expand Down
4 changes: 4 additions & 0 deletions packages/create-ponder/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# create-ponder

## 0.6.6

## 0.6.5

## 0.6.4

## 0.6.3
Expand Down
2 changes: 1 addition & 1 deletion packages/create-ponder/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "create-ponder",
"version": "0.6.4",
"version": "0.6.6",
"type": "module",
"description": "A CLI tool to create Ponder apps",
"license": "MIT",
Expand Down
4 changes: 4 additions & 0 deletions packages/eslint-config-ponder/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# eslint-config-ponder

## 0.6.6

## 0.6.5

## 0.6.4

## 0.6.3
Expand Down
2 changes: 1 addition & 1 deletion packages/eslint-config-ponder/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "eslint-config-ponder",
"version": "0.6.4",
"version": "0.6.6",
"description": "ESLint config for Ponder apps",
"license": "MIT",
"main": "./index.js",
Expand Down

0 comments on commit 6ca983b

Please sign in to comment.