Skip to content

Commit 623ee20

Browse files
authored
Merge pull request #1676 from drift-labs:chester/fix-cadence-account-loader
refactor(ui): add callback logic, fix polling frequency update
2 parents 25e2a38 + b75f747 commit 623ee20

File tree

1 file changed

+66
-30
lines changed

1 file changed

+66
-30
lines changed

sdk/src/accounts/customizedCadenceBulkAccountLoader.ts

Lines changed: 66 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,9 @@ import { v4 as uuidv4 } from 'uuid';
55

66
export class CustomizedCadenceBulkAccountLoader extends BulkAccountLoader {
77
private customIntervalId: NodeJS.Timeout | null;
8+
private currentPollingFrequency: number | null;
89
private accountFrequencies: Map<string, number>;
9-
private lastPollingTime: Map<string, number>;
10+
private lastPollingTimes: Map<string, number>;
1011
private defaultPollingFrequency: number;
1112

1213
constructor(
@@ -16,8 +17,9 @@ export class CustomizedCadenceBulkAccountLoader extends BulkAccountLoader {
1617
) {
1718
super(connection, commitment, defaultPollingFrequency);
1819
this.customIntervalId = null;
20+
this.currentPollingFrequency = null;
1921
this.accountFrequencies = new Map();
20-
this.lastPollingTime = new Map();
22+
this.lastPollingTimes = new Map();
2123
this.defaultPollingFrequency = defaultPollingFrequency;
2224
}
2325

@@ -32,12 +34,12 @@ export class CustomizedCadenceBulkAccountLoader extends BulkAccountLoader {
3234
}> = [];
3335

3436
for (const [key, frequency] of this.accountFrequencies.entries()) {
35-
const lastPollTime = this.lastPollingTime.get(key) || 0;
37+
const lastPollTime = this.lastPollingTimes.get(key) || 0;
3638
if (currentTime - lastPollTime >= frequency) {
3739
const account = this.accountsToLoad.get(key);
3840
if (account) {
3941
accountsToLoad.push(account);
40-
this.lastPollingTime.set(key, currentTime);
42+
this.lastPollingTimes.set(key, currentTime);
4143
}
4244
}
4345
}
@@ -66,23 +68,28 @@ export class CustomizedCadenceBulkAccountLoader extends BulkAccountLoader {
6668
}
6769
}
6870

71+
/**
72+
* Updates the polling frequency for an account. This affects all callbacks attached to this account.
73+
*
74+
* @param publicKey The public key of the account to set the custom polling frequency for
75+
* @param newFrequency The new polling frequency in ms
76+
*/
6977
public setCustomPollingFrequency(
7078
publicKey: PublicKey,
7179
newFrequency: number
7280
): void {
7381
const key = publicKey.toBase58();
7482
this.accountFrequencies.set(key, newFrequency);
75-
this.lastPollingTime.set(key, 0); // Reset last polling time to ensure immediate load
83+
this.lastPollingTimes.set(key, 0); // Reset last polling time to ensure immediate load
7684
this.restartPollingIfNeeded(newFrequency);
7785
}
7886

7987
private restartPollingIfNeeded(newFrequency: number): void {
80-
const currentMinFrequency = Math.min(
81-
...Array.from(this.accountFrequencies.values()),
82-
this.defaultPollingFrequency
83-
);
84-
85-
if (newFrequency < currentMinFrequency || !this.customIntervalId) {
88+
if (
89+
(this.currentPollingFrequency &&
90+
newFrequency < this.currentPollingFrequency) ||
91+
!this.customIntervalId
92+
) {
8693
this.stopPolling();
8794
this.startPolling();
8895
}
@@ -97,9 +104,10 @@ export class CustomizedCadenceBulkAccountLoader extends BulkAccountLoader {
97104
* @returns A unique callback ID that can be used to remove this specific callback later
98105
*
99106
* The method will:
100-
* 1. Create a new callback mapping for the account
101-
* 2. Set up polling frequency tracking for the account
102-
* 3. Reset last polling time to 0 to ensure immediate data fetch
107+
* 1. Create a new callback mapping for the account if it doesn't exist already
108+
* 2. Set up polling frequency tracking for the account if it doesn't exist already. If previous polling frequency is faster than the new one,
109+
* we will use the previous frequency.
110+
* 3. Reset last polling time to 0 to ensure data fetch is triggered on the next poll. Note that this does not mean the account will be fetched immediately.
103111
* 4. Automatically restart polling if this account needs a faster frequency than existing accounts
104112
*/
105113
public async addAccount(
@@ -108,28 +116,53 @@ export class CustomizedCadenceBulkAccountLoader extends BulkAccountLoader {
108116
customPollingFrequency?: number
109117
): Promise<string> {
110118
const callbackId = uuidv4();
111-
const callbacks = new Map<string, (buffer: Buffer, slot: number) => void>();
112-
callbacks.set(callbackId, callback);
113-
const newAccountToLoad = {
114-
publicKey,
115-
callbacks,
116-
};
117-
this.accountsToLoad.set(publicKey.toString(), newAccountToLoad);
119+
const existingAccountToLoad = this.accountsToLoad.get(publicKey.toString());
120+
121+
if (existingAccountToLoad) {
122+
existingAccountToLoad.callbacks.set(callbackId, callback);
123+
} else {
124+
const callbacks = new Map<
125+
string,
126+
(buffer: Buffer, slot: number) => void
127+
>();
128+
callbacks.set(callbackId, callback);
129+
const newAccountToLoad = {
130+
publicKey,
131+
callbacks,
132+
};
133+
this.accountsToLoad.set(publicKey.toString(), newAccountToLoad);
134+
}
118135

119136
const key = publicKey.toBase58();
120-
const frequency = customPollingFrequency || this.defaultPollingFrequency;
121-
this.accountFrequencies.set(key, frequency);
122-
this.lastPollingTime.set(key, 0); // Reset last polling time to ensure immediate load
137+
const previousFrequency =
138+
this.accountFrequencies.get(key) || this.defaultPollingFrequency;
139+
const updatedFrequency =
140+
customPollingFrequency && customPollingFrequency < previousFrequency
141+
? customPollingFrequency
142+
: previousFrequency;
143+
144+
this.accountFrequencies.set(key, updatedFrequency);
145+
this.lastPollingTimes.set(key, 0); // Reset last polling time to ensure immediate load
123146

124-
this.restartPollingIfNeeded(frequency);
147+
this.restartPollingIfNeeded(updatedFrequency);
125148

126149
return callbackId;
127150
}
128151

129-
public removeAccount(publicKey: PublicKey): void {
130-
const key = publicKey.toBase58();
131-
this.accountFrequencies.delete(key);
132-
this.lastPollingTime.delete(key);
152+
public removeAccount(publicKey: PublicKey, callbackId: string): void {
153+
const existingAccountToLoad = this.accountsToLoad.get(publicKey.toString());
154+
155+
if (existingAccountToLoad) {
156+
existingAccountToLoad.callbacks.delete(callbackId);
157+
158+
if (existingAccountToLoad.callbacks.size === 0) {
159+
this.bufferAndSlotMap.delete(publicKey.toString());
160+
this.accountsToLoad.delete(existingAccountToLoad.publicKey.toString());
161+
const key = publicKey.toBase58();
162+
this.accountFrequencies.delete(key);
163+
this.lastPollingTimes.delete(key);
164+
}
165+
}
133166

134167
if (this.accountsToLoad.size === 0) {
135168
this.stopPolling();
@@ -154,6 +187,8 @@ export class CustomizedCadenceBulkAccountLoader extends BulkAccountLoader {
154187
this.defaultPollingFrequency
155188
);
156189

190+
this.currentPollingFrequency = minFrequency;
191+
157192
this.customIntervalId = setInterval(() => {
158193
this.handleAccountLoading().catch((error) => {
159194
console.error('Error in account loading:', error);
@@ -167,8 +202,9 @@ export class CustomizedCadenceBulkAccountLoader extends BulkAccountLoader {
167202
if (this.customIntervalId) {
168203
clearInterval(this.customIntervalId);
169204
this.customIntervalId = null;
205+
this.currentPollingFrequency = null;
170206
}
171-
this.lastPollingTime.clear();
207+
this.lastPollingTimes.clear();
172208
}
173209

174210
public clearAccountFrequencies(): void {

0 commit comments

Comments
 (0)