-
Notifications
You must be signed in to change notification settings - Fork 289
Static HTTP responses #3250
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
Static HTTP responses #3250
Conversation
I think we're OK here; I'm reasonably confident that |
|
Based on gazing at the code for a bit my hunch is that having no component associated with the trigger will ultimately be best.
|
I think that's what I do but I think I needed a placeholder executor type because that stuff gets set up before I can arrive there... maybe I'm wrong, I did go through some iterations and might have ended up with dead code |
If you have a dummy component ID then yeah you would need a matching executor; that whole comment apples only to an alternate-universe no-component-id PR. |
06a815f to
8a24614
Compare
|
I have backed out the host requirement, reverted to using Options for the trigger config, and used a type for the trigger lookup key rather than synthesising a fake component ID. (The RouteMatch can't return the TriggerConfig directly because circularity. We could have it return the trigger ID rather than the component ID, but at the moment we use the route match key for printing component names against routes, so some refactoring would be needed there.) Kept it as two commits for now, will squash if this looks less unacceptable. |
1e8207e to
5e0b7e0
Compare
| } | ||
|
|
||
| impl HttpTriggerConfig { | ||
| pub fn lookup_key(&self, trigger_id: &str) -> anyhow::Result<crate::routes::TriggerLookupKey> { |
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.
SERIALISATION TYPES SHOULD BE FOR 1. SERIALISING 2. DESERIALISING 3. NOTHING ELSE AND THE MOST IMPORTANT OF THESE IS NOTHING ELSE
– Abraham Lincoln (I think)
lann
left a comment
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.
Approach looks reasonable to me!
|
|
||
| // Now that router is built we can merge duplicate routes by component | ||
| let component_trigger_configs = HashMap::from_iter(component_trigger_configs); | ||
|
|
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 wonder if it would be easier to partition into component_trigger_configs and static_trigger_configs here?
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.
@lann I tried this in the "Plan C" commit. I'm not sure it's easier. It does front load some of the fiddliness, but I can't imagine it's a big perf benefit, and in terms of code clarity I think it just moves complexity around. But I've put it up so you can take a look and let me know if this is what you were envisaging and if so how you feel about it.
(I realise "Plan C" still needs a bit of polishing if we decide to go this route.)
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.
This suggestion was just a hunch. If it isn't clearly better then pick your favorite.
a3b3e9e to
fb5f563
Compare
e528399 to
7597a2c
Compare
lann
left a comment
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.
A couple of minor suggestions for your consideration.
| /// A static response to be served directly by the host | ||
| /// without instantiating a component. | ||
| #[derive(Clone, Debug, Deserialize, Serialize)] | ||
| pub struct StaticResponse { |
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 we require at least one of these to be set? It's certainly logically valid to use all defaults but seems unlikely to be intentional.
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.
My inclination is to punt this: there are all sorts of things that are unlikely to be intentional, and this seems like a low-likelihood omission which will be spotted as soon as you use the route.
(I admit bias because I started looking at it and it turned into more of a faff than I expected, although some of that may have been overthinking.)
crates/routes/src/lib.rs
Outdated
| // This is a bit lazy but it saves a lot of faff in the conventional case | ||
| impl From<&str> for TriggerLookupKey { | ||
| fn from(value: &str) -> Self { | ||
| component_key(value) | ||
| } | ||
| } |
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.
This is pretty surprising when reading the tests. Maybe you should be even lazier?
| // This is a bit lazy but it saves a lot of faff in the conventional case | |
| impl From<&str> for TriggerLookupKey { | |
| fn from(value: &str) -> Self { | |
| component_key(value) | |
| } | |
| } | |
| fn test_router(component_routes: impl IntoIterator<Item = (&str, &str)>) -> Router { | |
| ... | |
| } |
Signed-off-by: itowlson <[email protected]>
7597a2c to
058b175
Compare
Fixes #3242. Example
spin.tomlfragment:This is, in some ways, a bit unwieldy, because the assumption that a trigger maps to a component is fairly deeply embedded. We seem to need a new handler type that can never be executed, and there is some faff around assigning a fake component ID, because everything currently depends on component IDs for lookup. If folks feel we should attempt a larger refactor then I can give it a go before fleeing into the hills.
An implication of this is that applications with static responses can't reliably interact with selective deployment (
spin up -c). I believe thatspin up -cretains triggers associated with the selected components, and static response triggers are associated with no component. An alternative design that would avoid this would be to have static responses as a pseudo-component type rather than a trigger behaviour (that is, the trigger still points to a named component, but the component is... not a component! ha ha!) - however, this feels extremely can-of-worms-tastic, as the component schema is embedded fairly deeply through Spin. Again, I can investigate it if that's something we want to explore.I did consider synthesising an in-memory (or temporary filesystem) component that would respond with the static response, but that seemed like it just created large amounts of hairiness elsewhere. However, it would allow applications that used static responses to be deployed to existing hosts.
As it is, I think we need a
host_requirementsentry in the lockfile to ensure that hosts understand the new field. (And this field is app level because we don't have trigger-levelmust_understand, so it won't be bypassed by selective deployment, even though selective deployment exterminates static response triggers.) Although maybe I am wrong because this is a schema change so hosts will automatically fail by syntax rather than needing to be warned about semantics? I've put it in a separate commit in case we can back it out.Draft because I need to write tests because I always forget to do those first, but ready for initial feedback on the approach and on the host-requirements stuff.