-
Notifications
You must be signed in to change notification settings - Fork 317
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
feat(boundary): setup of rate-limit canister #1961
base: master
Are you sure you want to change the base?
feat(boundary): setup of rate-limit canister #1961
Conversation
Co-authored-by: r-birkner <103420898+r-birkner@users.noreply.github.com>
acca095
to
2d6a3fe
Compare
2d6a3fe
to
db4c0a6
Compare
Err: text; | ||
}; | ||
|
||
type DiscloseRulesByIncidentIdResponse = variant { |
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 see that you have a lot of
type XResponse = variant {
Ok;
Err: text;
};
maybe it'd make sense to consolidate those somehow?
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.
These types could be consolidate at some later point. But once consolidated the extensibility/flexibility is lost. Probably some Ok
variant will contain messages, i haven't yet carefully thought through.
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, but couldn't that just be a new Response type? I didn't mean you can only respond with this smaller type. E.g
type EmptyResponse = variant {
Ok;
Err: text;
};
type ListResponse = variant {
Ok: vec RuleId,
Err: text;
};
service: {
disclose: (DiscloseArg) -> EmptyResponse;
list: (ListArg) -> ListResponse;
};
type InputConfig = record { | ||
schema_version: SchemaVersion; // schema version used to serialized the rules | ||
rules: vec InputRule; | ||
}; |
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.
Should it be possible when specifying rules to also specify whether they are public or not? Or do you have to basically set the config, and then in another call disclose rules? I guess what I'm asking is "what does a normal user flow look like?"
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.
The expected flow is:
- Each newly added rule is confidential by default
- To open the rule for public viewing a separate call to
disclose_()
function is needed
We could indeed add an additional fieldpolicy
withprivate/public
, but it seems to be unnecessary. If needed it can be added.
disclose_rules_by_rule_ids: (vec RuleId) -> (DiscloseRulesByRuleIdsResponse); | ||
|
||
// Make the viewing of the specified rules related to an incident ID publicly accessible | ||
disclose_rules_by_incident_id: (IncidentId) -> (DiscloseRulesByIncidentIdResponse); |
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.
Any thoughts on consolidating these two disclose methods? e.g
type DiscloseArg = variant {
Rules: vec RuleId;
Incidents: vec IncidentId;
};
disclose: (vec DiscloseArg) -> (DiscloseResponse);
and similarly for get_rules
:
type ListArg = variant {
Rules: vec RuleId;
Incidents: vec IncidentId;
};
list: (vec ListArg) -> (ListResponse);
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 do like the disclose
one! but for get_rules
it would be strange as for a RuleId
it returns a single rule.
mod types; | ||
|
||
#[ic_cdk_macros::update] | ||
fn get_config(version: Option<Version>) -> GetConfigResponse { |
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.
Friendly suggestion - you may not agree with it. Notice that canisters don't really have a main
function, so it's hard to gauge "what runs first". This can make it tricky to have a clear understanding of the order of operations happening in the canister upon startup (the various initialization steps, like declaring stable memory, canister methods, etc). For that reason, my suggestion would be to not rush to break up the canister code into separate files. Instead, treat canister/lib.rs
similarly to how you would treat your main.rs
file, meaning configure all your initialization logic there sequentially, like you would do in a main
function. So in this case:
# lib.rs
... define stable memory
... define dependencies that will be used in your canister methods
... define canister methods
then on a per-need basis you'd create new files to host things that get imported into your lib.rs. All this is mostly so that it's easier to understand the flow of the canister. As it is right now, you would have to ask yourself, what's happening first? Stable memory in storage.rs? Canister methods in canister.rs?
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.
Notice that canisters don't really have a main function, so it's hard to gauge "what runs first".
Yes, canister is an actor.
For that reason, my suggestion would be to not rush to break up the canister code into separate files.
I understand. Since I have already prototyped the canister locally, i wanted to have at least a minimum separation of files. For example canister/types.rs
and canister/canister.rs
(lib.rs) make sense already now IMO. Stable memory variables and init
i can add in the next MR. Wdyt? However, I still wanted a working canister at this point.
c90662c
to
9c7347a
Compare
This MR sets some boiler plate code for the
rate-limit
canister:candid
types are stored inrs/boundary_node/rate_limits/api
as alib
crate. This allows to reuse this interface e.g. in the canister-client (4).ic/rs/boundary_node/rate_limits/canister
(as alib
crate) and implements one functionget_config()
from the candidinterface.did
. Canister uses one variable stored in the stable memory for testing.dfx
deployment of the canister can be done withdfx deploy rate_limit_canister --network playground --no-wallet
dfx
command