-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.ts
114 lines (103 loc) · 3.98 KB
/
main.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
import { HttpStatus, INestApplicationContext } from '@nestjs/common'
import { NestFactory } from '@nestjs/core'
import { Callback, Context, Handler } from 'aws-lambda'
import { Logger } from 'feecollector-report-common/logger'
import { EventsScraperModule } from './events-scraper.module'
import { FeeCollectorEventsScraper } from './events-scraper.service'
import { ChainKey } from '@lifi/types'
/** Private logger */
const logger = Logger.child({
label: 'EventsScraperMain',
})
/**
* Serverless Function handler for the FeeCollectorEventsScraper main
* function / entry point to initiate an event scraping session of
* onchain FeeCollected events against the specified blockchain.
*
* @param event The triggering HTTP event from an API Gateway
* @param _context Execution context of the function runtime environment
* @param _callback Callback injected to this function to forward its response
* @returns response status and body message
*/
export const scrapFeeCollectorEvents: Handler = async (
event: any,
_context: Context,
_callback: Callback
) => {
const { chain } = event.pathParameters
logger.debug(
`Lambda function invoked for Scraping events from chain '${chain}' - Context: ${JSON.stringify(_context)}`
)
return await startScraping(chain, _context.awsRequestId)
}
/** Local persistence of an already created application context - Required for the Lambda function's runtime context */
let appContext: INestApplicationContext
/**
* Avoid recreating an application context if a previously created one
* is still available in the context of the serverless function
*/
async function getAppContext(): Promise<INestApplicationContext> {
if (appContext == null) {
appContext = await NestFactory.createApplicationContext(EventsScraperModule, {
logger:
process.env.NODE_ENV === 'production'
? ['fatal', 'error', 'warn']
: ['fatal', 'error', 'warn', 'log', 'debug'],
}).catch((err) => {
logger.error(`Application context has failed to init`, err)
return Promise.reject(err)
})
}
return appContext
}
/**
* Initiates the FeeCollectorEventsScraper service and starts a blockchain scanning session.
* @param chainKey the key of the blockchain to scan
* @param requestId the request ID
* @returns an http-based response status and body message
*/
async function startScraping(chain: string, requestId: string) {
// Validate the input chain key
if (!Object.values(ChainKey).includes(<ChainKey>chain)) {
logger.error(`Invalid chain key '${chain}' in request ${requestId}`)
return {
statusCode: HttpStatus.BAD_REQUEST,
body: JSON.stringify({
message: `Unsupported chain '${chain}'`,
}),
}
}
// Build the execution context
const appContext = await getAppContext()
const appService = appContext.get(FeeCollectorEventsScraper)
const chainKey = <ChainKey>chain
// Scrap latest FeeCollected events for the specified chain
try {
const res = await appService.scrapFeeCollectorEvents(chainKey)
return {
statusCode: HttpStatus.OK,
body: JSON.stringify(res),
}
} catch (error: any) {
const msgGenericMsg = `Failed to scrap FeeCollector events from chain '${chainKey}'`
logger.error(`${msgGenericMsg} - Events Scraping session '${requestId}' ABORTED\n`, error)
return {
statusCode: HttpStatus.INTERNAL_SERVER_ERROR,
body: JSON.stringify({
message: msgGenericMsg,
// error: error.response ?? error.message
}),
}
}
}
// Local dev entry point emulating the launch of the `FeeCollectorEventsScraper` function.
// For automated local launch only - It has no effect in a serverless deployment context
if (process.env.DEV_MODE === '1') {
const startTime = new Date()
startScraping(ChainKey.POL, startTime.toISOString())
.then((res) => {
const duration = new Date().getTime() - startTime.getTime()
logger.info(`Process duration: ${duration / 1000}s - Result: ${JSON.stringify(res)}`)
})
.finally(() => process.exit())
}