-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Created dedicated classes for Workflow,Node,Edge and Execution #41
Conversation
8c34ba6
to
2f929b4
Compare
New and removed dependencies detected. Learn more about Socket for GitHub ↗︎
|
2f929b4
to
06c9883
Compare
…Be(expected.maxExecution);'
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@v9n this PR is ready for review. The major change is to convert builder.ts to TriggerFactory and NodeFactory to include strong typing for building input parameters.
The maxExecution
parameter returned from AVS seems to be inconsistent with the input. Currently the tests are failing in local, but they are all due to this line:
expect(actual.maxExecution).toBe(expected.maxExecution);
at the end of tests/utils.ts
. Commenting that line will result in all green from tests.
console.log("CronTrigger.fromResponse.obj:", obj); | ||
return new CronTrigger({ | ||
...obj, | ||
type: TriggerTypes.CRON, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hey @chrisli30 these type
parameter isn't needed when sending to protobuf. we can remove them.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Understood, but these type
is not sent to AVS currently, but as an intrinsic variable of the SDK’s Trigger.
Each Trigger has their own data struct, without a shared type
variable, it‘s hard to use shared code, in other words, class inheritance.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we can juse use sth as above with .getType()
method define in the parent Trigger class to get class name and parse out the type.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, that will work. However, I’m trying to achieve something extra: to directly reference the code you defined in the protobuf, which is the below code.
export namespace TaskTrigger {
export enum TriggerTypeCase {
TRIGGER_TYPE_NOT_SET = 0,
MANUAL = 2,
FIXED_TIME = 3,
CRON = 4,
BLOCK = 5,
EVENT = 6,
}
}
Even if we getType() the classNames, they are defined by the sdk. If we change anything in the protobuf, the classNames will need manual update as well.
|
||
return new BlockTrigger({ | ||
...obj, | ||
type: TriggerTypes.BLOCK, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no need to pass type
. you will notice that in toRequest
we dont need to send type to server.
and when you're in BlockTrigger
class, you definetely know its type. no need to set this redundant param
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree, we can use a typeof BlockTrigger
to tell the type, but that’s not ideal, due to the below two reasons:
- The result of the
typeof
can’t directly map to the original type’s values, such asTriggerTypes.BLOCK
. - The
typeof
is not conventional and a little hacky, and we rarely use it.
I think the reason protobuff doesn’t need a type
variable is that it does not support class inheritance, and use oneOf
instead. However, the fact that there are 5 optional parameters, epochs
,cron
, conditions
, etc. , using oneOf
on a single struct, confused me. As a caller, it’s hard to figure out what parameters to choose.
Additionally, no matter what trigger type a caller chooses, the data field is all called data
. I also kept the inner variable original, so we know that the inner data is a cron
, epochList
, or conditionsList
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i mean is there a reason we couldn't do this?
class Trigger {
getType(): string {
// parse class name to get type
return this.constructor.name.substr(0, this.constructor.name.length - 7);
}
}
class FooTrigger extends Trigger {
}
class BarTrigger extends Trigger {
}
const a = new FooTrigger();
console.log("im", a.getType());
const b = new BarTrigger();
console.log("im", b.getType());
Result
npx tsc a.ts
❯ node a.js
im Foo
im Bar
it save users the work of manually passing the type parameter. BlockTrigger is definetely a block, just by infering the class name as i show above
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same reason as above. There’s no FooTrigger can be or should be defined as a type, except for the original protobuf values.
export enum TriggerTypeCase {
TRIGGER_TYPE_NOT_SET = 0,
MANUAL = 2,
FIXED_TIME = 3,
CRON = 4,
BLOCK = 5,
EVENT = 6,
}
* @param props | ||
* @returns | ||
*/ | ||
static create(props: TriggerProps): Trigger { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do you think this just cause extra unncecessary step?
trigger: TriggerFactory.create({
name: "blockTrigger",
type: TriggerTypes.BLOCK,
data: { interval: 5 },
}),
vs
trigger: new BlockTrigger({name: 'every 5 block trigger', interval: 5})
no need to pass type, and wrap everything into data
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Due to class inheritance, all Trigger class needs to share the same variable name, which is data
.
Also, it’s really hard to get the typescript type definition right, with some of the class input being number
type, but others an object
or array
type, so a common structure data: object
was needed.
We could do data: 5
, but I found data: {interval: 5}
is more descriptive.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no i mean just do
trigger: BlockTrigger.create({name: 'every 5 block trigger', interval: 5})
a user know exactlt what parameter a block trigger need based on the type def of the blcok trigger.
there is no value to adding the below:
TriggerFactory.create({
name: "ever 5 block",
type: TriggerTypes.BLOCK,
data: { interval: 5 },
}),
Unless we do other conversion and dynamic calculateion, right now we literally just switch type then invoke the underlying class directly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, we can. I chose to do this way
TriggerFactory.create({
name: "ever 5 block",
type: TriggerTypes.BLOCK,
data: { interval: 5 },
}),
It’s a little extra code to keep a unified format for all 5 triggers.
The max execution issue is fixed here AvaProtocol/EigenLayer-AVS#55 (comment) and the local dev test is fixed now. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we can move forward with the PR. but imho we cause extra work with the factory.
tests/getAddresses.test.ts
Outdated
const salt1 = "12345"; | ||
const salt2 = "0"; | ||
const createdWallet1 = await client.createWallet({ salt: salt1 }, { authKey }); | ||
const createdWallet2 = await client.createWallet({ salt: salt2 }, { authKey }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@chrisli30 i included multiple calls to prove that this call is idempotent regardless how many time we call it. you removed the call will make us lost that assertion.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oh I see, I recognized those typos ... just added them back.
This PR serves serveral purposes to improve the handling of Node and Trigger in the following ways:
avs_pb.js
. The way protobuf usesoneOf
to create data structure is unconventional to Typescript.Usage example of create a new workflow:
TODOs:
sync-protobuf
.tests/createTask.test.ts