-
Notifications
You must be signed in to change notification settings - Fork 321
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
RFC: isolating a stable core #162
Comments
An important question here: as the dust settles from #156, can we find ways to make it easier to write middleware that works across multiple frameworks? E.g., Actix has its own notion of middleware that's not too far off from Tide's. But it's not obvious that the differences can be easily bridged. Maybe it's possible to define a "least common denominator" interface that offers generic wrappers for various frameworks. |
Having a universal middleware concept in the Rust web-ecosystem is something I look forward to. In the Ruby community, for example, every framework builds on Rack middleware. I see this as the sole factor that allows for (some) code reuse across frameworks. My questions would be:
Edit (from @aturon): I've created a dedicated issue for further discussion along these lines. |
I think we can probably follow in gloo's footsteps here, and create a whole lot of subcrates + a skeleton to RFC a design for a crate. This would allow us to build out a fair share of middleware without incurring too much of the maintenance overhead. Also in particular their approaches to versioning and release scope might be interesting to read up on. |
Glad to see this direction! Couple of quick thoughts:
|
@prasannavl re: logger, I think following the footsteps of actix would be a good idea. Simply use the macros from the log crate and users of the framework can use a crate which implements the |
@bIgBV - That's exactly what the |
@rolftimmermans great comment -- I liked it so much I've moved it to its own issue, as I think cross-framework middleware deserves its own focused discussion. (That said, as folks have noted in this thread, there's some potential impact on where middleware lives and how it's named etc, depending on whether it's Tide-specific) |
While there are advantages of keeping core small and then building app with pluggable ecosystem crates, I am more in favour of a meta crate that pulls together necessary bits to get me started. The basic things should all be provided by the crate. |
I'd rather prefer it handled outside of tide for the time being, as the tide story first becomes production ready and has a little bit of time to stabilise. This will put tide in a much better place on how best to do this. I've been examining how to get this up and running in I've been thinking of helper patterns similar to |
Discussions after today's meeting seemed to center around the need to separate Tide core from contributed extensions that, while they may be common, aren't needed for every application that depends on Tide. Based on an idea from @bIgBV, I propose the following:
#175 is a solid example of a feature that essentially all Tide apps will need, while session handling is a concern that's slightly out of scope for core, in my opinion. |
We had some extensive discussion on Discord, which led to the following. Goals
Proposal(from @yoshuawuyts)
|
@rustasync/maintainers would anyone be interested in picking up this issue for this sprint? It seems like this would likely make the biggest structural improvement to our process, and free us up to do more experiments, and iterate faster ✨ |
I can pick this up! |
You're welcome to it, @wafflespeanut. I'll be on the lookout for a PR. Thanks for helping out! |
@wafflespeanut - Awesome! Splitting this up into smaller units to make this more manageable into smaller PRs with the current middlewares Isolating Core - Stage 1Precursor(Non breaking, foundation bits for the entire organisational structure):
Core Isolation(Initial run, we could even do most of the isolation in a non-breaking way - hopefully even everything, but fingers crossed and assume breaking for now)
Before next releaseMiddlewares
Others
|
We can bikeshed on crate names later. I don't think that's the most critical portion of this discussion. Ideally, the PR addressing this RFC should initially focus on the following: Splitting Tide core into smaller crates: Before we move any new code into this repo (from Surf or elsewhere). It makes sense to document the expected outcome. Once the split between Tide core and middleware is complete, I expect the source tree will have two primary folders in the root: I'd also like to see dependencies for example code moved out of Tide's dependency list. However, I'm aware that some dependencies are shared between examples (serde, for one), which may complicate this suggestion. Which extensions and middleware become their own crates? I think @prasannavl's comment above is a good place to start. Cookies can be split into The above text encapsulates minimal changes that I think would satisfy the RFC. We can decide on the naming conventions of new crates once the bulk of this work is completed. |
@secretfader - I think we've already discussed this, and there's no special We can move whatever needs to be in the core later. For now, I think we just split off and hit the ground running marking this as a ground zero of sorts, with nothing in the core at the moment. Then, we can decide what moves to core in whatever evolved form after it has had time to stabilise. Also, I don't really see the problem with serde, however if it does indeed get into a problem splitting it into an example, then I'd label that a bug -- that needs to be fixed. Making the PR that does 1 now. Hopefully @wafflespeanut can chime in on what he'd like to pick up form there! :) |
@prasannavl I think you misunderstood my comment. I'm not suggesting we create a crate for commonly used middlewares at this stage. However, think it would be helpful to place any resulting crates into their own folder, |
Tokio, futures all of them follow this model of doing it in the root currently. Besides, everything other than tide itself is going to be a folder with middleware, so I don't see the point of the indirection at this stage. However, if you feel strongly about the organisation structure, perhaps we should arrive at a consensus there. (Note: This could totally be a different scenario when tide's mature and have so many that tide-contrib [ideally a repo] is needed for community extensions not directly supported by the tide maintainers) |
@yoshuawuyts - I can co-ordinate this with others interested. Have done some of the foundation bits as well. I know you're busy on |
I'm thinking the distinction of I could imagine there would be a way to setup feature flags for Tide that by default you get what you need. And then there's a feature that when enabled removes all dependencies, and you can configure everything yourself. I suspect that adding in this mechanism would be an extra 100 or so lines, but would allow us to streamline things reasonably (: Separately from that runtime's dir structure is pretty nice; we use |
One of the primary usecases of a separate If you expect to never have a semver breaking update of anything that gets graduated into |
@yoshuawuyts I think @Nemo157 put across what I had in mind beautifully with the future backed experience. It'd be simpler for the middleware crates to iterate and grow easily without tying into the whole batteries included tide. Target based dependencies fit naturally for the runtime world - but I think the That being said, if we don't have consensus - one way to delay this is to keep Also, while this is easily understood, will just iterate for the sake of completion -
Yes. I liked the structure when I saw in it |
@Nemo157 yeah, that was the exact idea I had in mind. Things only graduate once we're ready to commit them feeling like the external API is ready to be tied to Tide's stability model. But given that they'd be used internally to Tide a lot of the times, that constraint probably feels even more flexible. @prasannavl Up until now I was under the impression we'd achieved consensus on having a single top-level Tide vs Tide-CoreI feel we've seen a lot of experimentation around Similarly we can probably learn from syn, where a lot of the features are hidden behind the # full
[dependencies]
tide = "1.3.2"
# minimal
[dependencies]
tide = { version = "1.3.2", features = [ "bare" ] } Graduating dependenciesBut in order to encourage productivity, we probably want to provide people with ways of trying out new additions, after we feel that things might be good, but before we commit to stabilizing. # stable
[dependencies]
tide = "1.3.2"
# experimental
[dependencies]
tide = { version = "1.3.2", features = [ "cookies-experiment" ] } I'm not 100% convinced how important this last bit is, but it might be something to consider if we want to enable some nicer workflows. It's not something we have to decide now, but can revisit as we start thinking of graduating dependencies to stable. |
Just wanna chime in and say that I very much agree with @yoshuawuyts idea of having the default experience be as inclusive as possible. What always annoyed me so far with a lot of web service development in Rust is the shear number of imports and external crates required to explicitly mention. Having Similarly, I feel like we should be sparse with feature flags. Having a generic |
Before anything, let me clarify this: Everything that's being discussed above, from a user perspective is a single tide dependency only. User of tide just use tide. This is of relevance only to tide extension, development and middleware authors.
Yes. This is true. It appears I'm the one who didn't get the nuances of the details correctly. Sorry about that if it was my bad - I naturally ended up with the split, because that's the only way to really have I'll put things in context here:
|
You can still directly refer to |
# minimal
[dependencies]
tide = { version = "1.3.2", features = [ "bare" ] } this should be # minimal
[dependencies]
tide = { version = "1.3.2", default-features = false } or you're going to have a lot of issues related to bad feature interactions. If you want all features on by default you just need to specify all features in the |
@Nemo157 - Yes, this is the only way to allow for things to be in separate crates wihout
Very simply put features flags are easy to miss, pain to manage, rather than just a simple |
Tide is designed to be a highly modular, extensible framework, and #156 pushes us further in that direction.
There are a set of core concepts and interfaces:
App
andRoute
)Endpoint
interface, includingContext
Middleware
interfaceBeyond that, we have a number of implementations and extensions:
Various "extractors", which are now implemented as extension traits that work on
Context
. See forms for example.Middleware implementations, such as logging.
Response builders, like this one.
Tide's current design allow for a strong decoupling between the core interfaces and these various extensions, much like Flask. This raises some questions about how to approach development, as well as the UX for Tide.
Proposal: follow the Flask model (for now)
Since Tide is explicitly intended to foster re-usable, modular components that can work with other frameworks, it makes a lot of sense to take full advantage of the decoupling above. That would follow in Flask's footsteps, where there's an extensive ecosystem of independent extensions to the tiny core framework.
I propose that we:
Limit the
tide
crate itself to the core interfaces and APIs, and perhaps some extremely common extractors (the ones that are currently directly provided onContext
, likebody_json
.Move all other extractors, middleware, and response builders into small, separate crates -- and generally encourage a spirit of experimentation with lots of small crates trying out competing approaches.
Provide a unified "guide to Tide's ecosystem" as an entry point to all these extensions. This could be as simple as a list of links to crate docs.
Eventually, as we gain more experience, I imagine that some of these extensions will become de facto standard, and we might want to consider moving them into core. Likewise, I expect we'll want some "bundling" crates that set up a middleware stack for you, to make it very easy to get going with Tide. But these things can come later.
This approach would make it feasible to get the Tide core to 1.0 status relatively quickly, with the expectation that the APIs would remain stable for a while (let's say six months at least). Meanwhile, the various middlware crates etc can be versioned independently, freeing them to make breaking changes without any coordination.
Open questions
One open question: if we do take this direction, do we want separate repos or just separate crates? I worry a bit that if we get too aggressive about separating repos right now, it will be hard to follow what's happening. So I personally lean toward at least starting by having the other crates live within the tide repo, with a shared issue tracker, until we start hitting scaling problems.
wdyt?
The text was updated successfully, but these errors were encountered: