forked from farcasterxyz/hub-monorepo
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add unique peer map to sync engine to represent current active …
…peers (farcasterxyz#2120) ## Motivation - Current peer store keeps track of all hubs that successfully connected - However, peers may connect and never be seen again due to churn or change in Peer ID - We add TTL Map of peers that only adds peers, never deletes, and expires any peer that hasn't gossiped updates in 24 hours ## Change Summary - add unique peer map to sync engine to represent current active peers ## Merge Checklist _Choose all relevant options below by adding an `x` now or at any time before submitting for review_ - [x] PR title adheres to the [conventional commits](https://www.conventionalcommits.org/en/v1.0.0/) standard - [x] PR has a [changeset](https://github.com/farcasterxyz/hub-monorepo/blob/main/CONTRIBUTING.md#35-adding-changesets) - [x] PR has been tagged with a change label(s) (i.e. documentation, feature, bugfix, or chore) - [ ] PR includes [documentation](https://github.com/farcasterxyz/hub-monorepo/blob/main/CONTRIBUTING.md#32-writing-docs) if necessary. - [x] All [commits have been signed](https://github.com/farcasterxyz/hub-monorepo/blob/main/CONTRIBUTING.md#22-signing-commits) ## Additional Context If this is a relatively large or complex change, provide more details here that will help reviewers <!-- start pr-codex --> --- ## PR-Codex overview This PR introduces a unique peer map to track active peers in the sync engine of the Hubble app. It also adds a high-performance TTLMap for efficient entry expiration management. ### Detailed summary - Added unique peer map for active peers in the sync engine - Implemented TTLMap for automatic expiration of entries - Updated handling of peer discovery events - Enhanced peer contact management in the sync engine > The following files were skipped due to too many changes: `apps/hubble/src/utils/ttl_map.ts` > ✨ Ask PR-Codex anything about this PR by commenting with `/codex {your question}` <!-- end pr-codex -->
- Loading branch information
1 parent
094fe86
commit 2a82b3d
Showing
7 changed files
with
363 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
"@farcaster/hubble": patch | ||
--- | ||
|
||
feat: add unique peer map to sync engine to represent current active peers |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,142 @@ | ||
import { TTLMap } from "./ttl_map.js"; | ||
import { jest } from "@jest/globals"; | ||
|
||
describe("TTLMap", () => { | ||
jest.useFakeTimers(); | ||
|
||
test("size should accurately reflect non-expired entries", () => { | ||
const map = new TTLMap<string, number>(1000); | ||
|
||
expect(map.size()).toBe(0); | ||
|
||
map.set("a", 1); | ||
expect(map.size()).toBe(1); | ||
|
||
map.set("b", 2); | ||
expect(map.size()).toBe(2); | ||
|
||
jest.advanceTimersByTime(500); | ||
map.set("c", 3); | ||
expect(map.size()).toBe(3); | ||
|
||
jest.advanceTimersByTime(501); | ||
expect(map.size()).toBe(1); | ||
|
||
map.get("a"); // This should trigger cleanup of expired entry | ||
expect(map.size()).toBe(1); | ||
}); | ||
|
||
test("set should not double count when updating existing entries", () => { | ||
const map = new TTLMap<string, number>(1000); | ||
|
||
map.set("a", 1); | ||
expect(map.size()).toBe(1); | ||
|
||
map.set("a", 2); // Updating existing non-expired entry | ||
expect(map.size()).toBe(1); | ||
|
||
jest.advanceTimersByTime(1001); | ||
map.set("a", 3); // Updating expired entry | ||
expect(map.size()).toBe(1); | ||
}); | ||
|
||
test("delete should correctly update size for expired and non-expired entries", () => { | ||
const map = new TTLMap<string, number>(1000); | ||
|
||
map.set("a", 1); | ||
map.set("b", 2); | ||
expect(map.size()).toBe(2); | ||
|
||
map.delete("a"); | ||
expect(map.size()).toBe(1); | ||
|
||
jest.advanceTimersByTime(1001); | ||
expect(map.delete("b")).toBe(true); // Deleting expired entry | ||
expect(map.size()).toBe(0); | ||
}); | ||
|
||
test("get should update size when retrieving expired entries", () => { | ||
const map = new TTLMap<string, number>(1000); | ||
|
||
map.set("a", 1); | ||
expect(map.size()).toBe(1); | ||
|
||
jest.advanceTimersByTime(1001); | ||
expect(map.get("a")).toBeUndefined(); | ||
expect(map.size()).toBe(0); | ||
}); | ||
|
||
test("resetTTL should correctly handle expired and non-expired entries", () => { | ||
const map = new TTLMap<string, number>(1000); | ||
|
||
map.set("a", 1); | ||
expect(map.size()).toBe(1); | ||
|
||
jest.advanceTimersByTime(500); | ||
map.resetTTL("a"); | ||
expect(map.size()).toBe(1); | ||
|
||
jest.advanceTimersByTime(750); | ||
expect(map.get("a")).toBe(1); | ||
expect(map.size()).toBe(1); | ||
|
||
jest.advanceTimersByTime(251); | ||
map.resetTTL("a"); | ||
expect(map.size()).toBe(1); | ||
expect(map.get("a")).toBe(1); | ||
}); | ||
|
||
test("getAll should return only non-expired entries", () => { | ||
const map = new TTLMap<string, number>(1000); | ||
|
||
map.set("a", 1); | ||
map.set("b", 2); | ||
map.set("c", 3); | ||
|
||
jest.advanceTimersByTime(500); | ||
map.set("d", 4); | ||
|
||
jest.advanceTimersByTime(501); | ||
|
||
const allEntries = map.getAll(); | ||
expect(allEntries).toHaveLength(1); | ||
expect(allEntries[0]).toEqual(["d", 4]); | ||
expect(map.size()).toBe(1); | ||
}); | ||
|
||
test("clear should reset size to zero", () => { | ||
const map = new TTLMap<string, number>(1000); | ||
|
||
map.set("a", 1); | ||
map.set("b", 2); | ||
expect(map.size()).toBe(2); | ||
|
||
map.clear(); | ||
expect(map.size()).toBe(0); | ||
|
||
map.set("c", 3); | ||
expect(map.size()).toBe(1); | ||
}); | ||
|
||
test("size should be accurate after multiple operations", () => { | ||
const map = new TTLMap<string, number>(1000); | ||
|
||
map.set("a", 1); | ||
map.set("b", 2); | ||
map.set("c", 3); | ||
expect(map.size()).toBe(3); | ||
|
||
jest.advanceTimersByTime(500); | ||
map.delete("b"); | ||
map.set("d", 4); | ||
expect(map.size()).toBe(3); | ||
|
||
jest.advanceTimersByTime(501); | ||
map.get("a"); // This should trigger cleanup | ||
expect(map.size()).toBe(1); | ||
|
||
map.set("e", 5); | ||
map.resetTTL("d"); | ||
expect(map.size()).toBe(2); | ||
}); | ||
}); |
Oops, something went wrong.