Skip to content

Commit a304564

Browse files
authored
Merge pull request #20 from ora-io/dev
Dev
2 parents 35677b1 + 848fa6d commit a304564

File tree

25 files changed

+295
-37
lines changed

25 files changed

+295
-37
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "ora-stack",
3-
"version": "0.1.8",
3+
"version": "0.2.0",
44
"private": true,
55
"packageManager": "[email protected]",
66
"description": "",

packages/orap/README.md

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -154,10 +154,14 @@ Each `.event(...)` starts an `Event Flow`
154154

155155
Each `.task(...)` starts a `Task Flow`
156156

157+
**.use(handler: HandleFn)**
158+
- set the task middleware, which will be called in order, click here to see the [middlewares](#middlewares)
159+
157160
**.handle(handler: HandleFn)**
158-
- set the task handler, the most important property for a task.
159-
- `return true` to identify handle success, and entering `onSuccess`
160-
- `return false` to identify handle failed, and entering `onSuccess`
161+
- set the task handler, the most important property for a task, **you can think of this as a middleware**.
162+
- ~~`return true` to identify handle success, and entering `onSuccess`~~
163+
- ~~`return false` to identify handle failed, and entering `onFailed`~~
164+
- It will automatically detect success and failed and call the `onSuccess` and `onFailed` hooks
161165

162166
**.cache(sm: StoreManager)**
163167
- set the store to cache the tasks
@@ -194,6 +198,17 @@ Each `.task(...)` starts a `Task Flow`
194198
- back to the parent `Event Flow`, so that it can add another `.task`
195199
- e.g. `orap.event(...).task().another().task()`
196200

201+
### Middlewares
202+
203+
The middlewares are used in the `Task Flow` to handle the task processing, it's a chain of functions that can be called in order.
204+
205+
#### Features
206+
207+
- the last parameter of the handler is the `next` fn, so you have to call it to continue the next handler.
208+
- the penultimate parameter is the `TaskRaplized` object, which contains the task info.
209+
- you can pass parameters to the next handler by calling `next(param1, param2, ...)`, it will be passed to the next handler as arguments, note: you cannot pass `TaskRaplized` object and `next` fn to the next handler, it will pass the next handler with the `TaskRaplized` object and `next` fn automatically.
210+
211+
197212
### OO Style (Basic)
198213

199214
Note the following doesn't include task cache, it only calls `handle` every time it receives an event. So this service is only for demo, don't use it for production, otherwise it may miss events when service down.

packages/orap/examples/declarativeDemo/app.ts

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1+
/* eslint-disable prefer-rest-params */
12
import type { ContractEventPayload } from 'ethers'
2-
import { Logger, randomStr, redisStore } from '@ora-io/utils'
3+
import { Logger, objectKeys, randomStr, redisStore } from '@ora-io/utils'
34
import type { ListenOptions, ToKeyFn } from '../../src'
4-
import { Orap, StoreManager } from '../../src'
5+
import { Orap, StoreManager, getTaskContext } from '../../src'
56
import ABI from './erc20.abi.json'
67

78
const MAINNET_USDT_ADDR = '0xdAC17F958D2ee523a2206206994597C13D831ec7'
@@ -59,7 +60,10 @@ export function startDemo(options: ListenOptions, storeConfig?: any) {
5960

6061
async function handleTask(from: string, to: string, amount: number, _event: ContractEventPayload) {
6162
logger.log('[+] handleTask: from =', from, 'to =', to, 'amount =', amount)
62-
return true
63+
const args = objectKeys(arguments).map(k => arguments[k])
64+
65+
const { next } = getTaskContext(...args)
66+
await next()
6367
}
6468

6569
async function newEventSignalHook(from: string, to: string, amount: number, event: ContractEventPayload) {
@@ -70,5 +74,8 @@ async function newEventSignalHook(from: string, to: string, amount: number, even
7074

7175
async function handleTask_2(from: string, to: string, amount: number) {
7276
logger.log('[+] handleTask_2: from =', from, 'to =', to, 'amount =', amount)
73-
return true
77+
const args = objectKeys(arguments).map(k => arguments[k])
78+
79+
const { next } = getTaskContext(...args)
80+
await next()
7481
}

packages/orap/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "@ora-io/orap",
33
"type": "module",
4-
"version": "0.1.8",
4+
"version": "0.2.0",
55
"packageManager": "[email protected]",
66
"description": "",
77
"author": "Norman (nom4dv3), MuRong",

packages/orap/src/flow/interface.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ import type { Context, TaskRaplized } from '../task'
33
import type { Verse } from '../verse/interface'
44

55
export type ToKeyFn = (...eventLog: Array<any>) => Awaitable<string>
6-
export type HandleFn = (...eventLog: Array<any>) => Awaitable<boolean>
6+
export type NextFunction = (...args: any[]) => void
7+
export type HandleFn = (...args: any[]) => Awaitable<any>
78
export type HandleResultFn = (task: TaskRaplized) => Awaitable<void>
89
export type PrefixFn = ((...eventLog: Array<any>) => Awaitable<string>) | ((context?: Context) => string) // the later context one is kind of useless, can rm
910
export type Prefix = PrefixFn | string

packages/orap/src/flow/task.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ describe('TaskFlow', () => {
5454
const handler = vi.fn()
5555
const result = taskFlow.handle(handler)
5656
expect(result).toBe(taskFlow)
57+
expect(taskFlow.middlewares).toContain(handler)
5758
expect(taskFlow.handleFn).toBe(handler)
5859
})
5960

packages/orap/src/flow/task.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ export class TaskFlow implements Flow {
2828
handleFn: HandleFn = defaultHandleFn
2929
successFn: HandleResultFn = defaultSuccessFn
3030

31+
private _middlewares: Array<HandleFn> = []
32+
3133
failFn: HandleResultFn = async (task: TaskRaplized) => {
3234
await task.remove()
3335
}
@@ -38,6 +40,10 @@ export class TaskFlow implements Flow {
3840
private parentFlow: EventFlow,
3941
) { }
4042

43+
get middlewares() {
44+
return this._middlewares
45+
}
46+
4147
cache(sm: StoreManager) {
4248
this.sm = sm
4349
return this
@@ -73,6 +79,12 @@ export class TaskFlow implements Flow {
7379

7480
handle(handler: HandleFn): this {
7581
this.handleFn = handler
82+
this._middlewares.push(handler)
83+
return this
84+
}
85+
86+
use(middleware: HandleFn): this {
87+
this._middlewares.push(middleware)
7688
return this
7789
}
7890

packages/orap/src/index.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
1+
import { Orap } from './orap'
2+
13
export * from './orap'
24
export * from './flow'
35
export * from './verse'
46
export * from './signal'
57
export * from './store'
68
export * from './task'
9+
export * from './middlewares'
10+
export * from './utils'
11+
12+
export default Orap
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { ContractEventPayload } from 'ethers'
2+
import type { Providers } from '@ora-io/reku'
3+
import { getTaskContext } from '../utils'
4+
5+
export const CheckTransactionStatus = (provider: Providers) => {
6+
if (!provider)
7+
throw new Error('provider is required')
8+
9+
return async (...args: any[]) => {
10+
const { next } = getTaskContext(...args)
11+
const contractEventPayload = args.at(-3) as ContractEventPayload
12+
if (contractEventPayload instanceof ContractEventPayload) {
13+
const tx = await provider.provider.getTransactionReceipt(contractEventPayload.log.transactionHash)
14+
if (!tx || tx?.status === 0)
15+
throw new Error('Transaction failed')
16+
await next()
17+
}
18+
else {
19+
throw new TypeError('Invalid contract event payload')
20+
}
21+
}
22+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import type { HandleFn } from '../flow'
2+
import { getTaskContext } from '../utils'
3+
4+
export const HandleFailedMiddleware: HandleFn = async (...args: any[]) => {
5+
const { next, task } = getTaskContext(...args)
6+
7+
try {
8+
await next()
9+
}
10+
catch (error) {
11+
await task.flow.failFn(task)
12+
}
13+
}

0 commit comments

Comments
 (0)