Skip to content

Commit 3a9ea6f

Browse files
committed
handler function error handling
1 parent 2cbead6 commit 3a9ea6f

File tree

8 files changed

+133
-52
lines changed

8 files changed

+133
-52
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# v0.4.11 (Unreleased)
22
- fix: show error message when `arkive deploy` fails
3+
- feat: add maximum retry attempts to handler function. default of 5 retries
34

45
# v0.4.10
56
- fix: emit event when arkiver is synced

src/arkiver/arkiver.ts

+9-1
Original file line numberDiff line numberDiff line change
@@ -79,12 +79,20 @@ export class Arkiver extends EventTarget {
7979
this.syncedCount++
8080
if (this.syncedCount === Object.entries(dataSources).length) {
8181
logger('arkiver').info(
82-
`Arkiver synced - ${this.arkiveData.name}`,
82+
`All chains fully synced!`,
8383
)
8484
this.dispatchEvent(new Event('synced'))
8585
}
8686
})
8787

88+
dataSource.addEventListener('error', () => {
89+
logger('arkiver').error(
90+
`Error running ${chain}`,
91+
)
92+
93+
this.dispatchEvent(new Event('error'))
94+
})
95+
8896
await dataSource.run()
8997
this.sources.push(dataSource)
9098
}

src/arkiver/data-source.ts

+94-51
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ export class DataSource extends EventTarget {
110110
})
111111
private isLive = false
112112
private noDb: boolean
113+
private maxHandlerRetries = 5
113114

114115
constructor(
115116
params: {
@@ -578,27 +579,41 @@ export class DataSource extends EventTarget {
578579
})
579580

580581
const loggerKey = `${this.chain}-${contractId}-${event.eventName}`
581-
try {
582-
await handler.handler({
583-
eventName: event.eventName,
584-
client: this.client,
585-
store: this.store,
586-
event: formatLog(log, event),
587-
contract: getContract({
588-
abi: handler.abi,
589-
address: log.address,
590-
publicClient: this.client,
591-
}),
592-
logger: logger(loggerKey),
593-
})
594-
} catch (e) {
595-
error =
596-
`Event handler ${handler.handler.name} at block ${log.blockNumber} with arguments:${
597-
Object.entries(event.args ?? {}).map(([name, arg], idx) =>
598-
`\n ${idx} ${name}: ${arg}`
582+
583+
let retries = 0
584+
while (true) {
585+
try {
586+
await handler.handler({
587+
eventName: event.eventName,
588+
client: this.client,
589+
store: this.store,
590+
event: formatLog(log, event),
591+
contract: getContract({
592+
abi: handler.abi,
593+
address: log.address,
594+
publicClient: this.client,
595+
}),
596+
logger: logger(loggerKey),
597+
})
598+
break
599+
} catch (e) {
600+
error =
601+
`Event handler ${handler.handler.name} at block ${log.blockNumber} with arguments:${
602+
Object.entries(event.args ?? {}).map(([name, arg], idx) =>
603+
`\n ${idx} ${name}: ${arg}`
604+
)
605+
}\n${e.stack}`
606+
logger(loggerKey).error(error)
607+
retries++
608+
if (retries > this.maxHandlerRetries) {
609+
this.dispatchEvent(new Event('error'))
610+
logger(loggerKey).debug(
611+
`Max retries reached for handler ${handler.handler.name} at block ${log.blockNumber}, stopping ...`,
599612
)
600-
}\n\n${e.stack}`
601-
logger(loggerKey).error(error)
613+
this.stop()
614+
return
615+
}
616+
}
602617
}
603618
} else if (logOrBlock.type === 'block') {
604619
const block = logOrBlock as {
@@ -608,17 +623,31 @@ export class DataSource extends EventTarget {
608623

609624
for (const handler of block.handlers) {
610625
const loggerKey = `${this.chain}-${handler.name}`
611-
try {
612-
await handler({
613-
block: block.block,
614-
client: this.client,
615-
store: this.store,
616-
logger: logger(loggerKey),
617-
})
618-
} catch (e) {
619-
error =
620-
`Block handler ${handler.name} at block ${block.block.number}\n\n${e.stack}`
621-
logger(loggerKey).error(error)
626+
627+
let retries = 0
628+
while (true) {
629+
try {
630+
await handler({
631+
block: block.block,
632+
client: this.client,
633+
store: this.store,
634+
logger: logger(loggerKey),
635+
})
636+
break
637+
} catch (e) {
638+
error =
639+
`Block handler ${handler.name} at block ${block.block.number}\n${e.stack}`
640+
logger(loggerKey).error(error)
641+
retries++
642+
if (retries > this.maxHandlerRetries) {
643+
this.dispatchEvent(new Event('error'))
644+
logger(loggerKey).debug(
645+
`Max retries reached for handler ${handler.name} at block ${block.block.number}, stopping ...`,
646+
)
647+
this.stop()
648+
return
649+
}
650+
}
622651
}
623652
}
624653
} else if (logOrBlock.type === 'agnosticLog') {
@@ -645,27 +674,41 @@ export class DataSource extends EventTarget {
645674

646675
const loggerKey =
647676
`${this.chain}-${eventHandler.contractId}-${event.eventName}`
648-
try {
649-
await eventHandler.handler({
650-
eventName: event.eventName,
651-
client: this.client,
652-
store: this.store,
653-
event: formatLog(log, event),
654-
contract: getContract({
655-
abi: eventHandler.abi,
656-
address: log.address,
657-
publicClient: this.client,
658-
}),
659-
logger: logger(loggerKey),
660-
})
661-
} catch (e) {
662-
error =
663-
`Agnostic event handler ${eventHandler.handler.name} at block ${log.blockNumber} with arguments:${
664-
Object.entries(event.args ?? {}).map(([name, arg], idx) =>
665-
`\n ${idx} ${name}: ${arg}`
677+
678+
let retries = 0
679+
while (true) {
680+
try {
681+
await eventHandler.handler({
682+
eventName: event.eventName,
683+
client: this.client,
684+
store: this.store,
685+
event: formatLog(log, event),
686+
contract: getContract({
687+
abi: eventHandler.abi,
688+
address: log.address,
689+
publicClient: this.client,
690+
}),
691+
logger: logger(loggerKey),
692+
})
693+
break
694+
} catch (e) {
695+
error =
696+
`Agnostic event handler ${eventHandler.handler.name} at block ${log.blockNumber} with arguments:${
697+
Object.entries(event.args ?? {}).map(([name, arg], idx) =>
698+
`\n ${idx} ${name}: ${arg}`
699+
)
700+
}\n${e.stack}`
701+
logger(loggerKey).error(error)
702+
retries++
703+
if (retries > this.maxHandlerRetries) {
704+
this.dispatchEvent(new Event('error'))
705+
logger(loggerKey).debug(
706+
`Max retries reached for handler ${eventHandler.handler.name} at block ${log.blockNumber}, stopping ...`,
666707
)
667-
}\n\n${e.stack}`
668-
logger(loggerKey).error(error)
708+
this.stop()
709+
return
710+
}
711+
}
669712
}
670713
}
671714

src/arkiver/manifest-builder.ts

+3
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ import {
2020
} from '../deps.ts'
2121
import { getChainObjFromChainName } from '../utils.ts'
2222

23+
export const manifestVersion = 'v1'
24+
2325
export class Manifest<TName extends string = ''> {
2426
public manifest: ArkiveManifest
2527

@@ -36,6 +38,7 @@ export class Manifest<TName extends string = ''> {
3638
dataSources: {},
3739
entities: [],
3840
name: formattedName,
41+
version: manifestVersion,
3942
}
4043
}
4144

src/arkiver/types.ts

+1
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ export interface ArkiveManifest {
6060
// deno-lint-ignore no-explicit-any
6161
entities: { model: mongoose.Model<any>; list: boolean; name: string }[]
6262
name: string
63+
version: string
6364
}
6465

6566
export type DataSource = {

test-retries/.vscode/settings.json

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"deno.enable": true,
3+
"deno.unstable": true
4+
}

test-retries/deps.ts

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
export { formatUnits } from 'npm:viem'
2+
export {
3+
createEntity,
4+
type EventHandlerFor,
5+
Manifest,
6+
} from 'https://deno.land/x/robo_arkiver/mod.ts'

test-retries/manifest.ts

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { Manifest } from './deps.ts'
2+
3+
const manifest = new Manifest('simple')
4+
5+
manifest
6+
.chain('mainnet')
7+
.addBlockHandler({
8+
startBlockHeight: 17379257n,
9+
blockInterval: 20,
10+
handler: () => {
11+
throw new Error('test')
12+
},
13+
})
14+
15+
export default manifest.build()

0 commit comments

Comments
 (0)