tailhook / rotor

The mio-based framework for rust for doing I/O in simple and composable way (ABANDONED)
MIT License
361 stars 25 forks source link

Default Machine::spawned implementation #11

Closed seanmonstar closed 8 years ago

seanmonstar commented 8 years ago

Each time I've implemented Machine, I've used the exact same function body for the spawned method. Perhaps a default implementation could be provided?

fn spawned(self, scope: &mut Scope<Self::Context>) -> Response<Self, Self::Seed> {
    Response::ok(self)
}

Slightly related, but perhaps more controversial: Maybe Machine could provide default stubs for other less important methods also, like mio::Handler does. Such as timeout and wakeup defaulting to just return ok(self).

tailhook commented 8 years ago

@seanmonstar any pointers? My use cases are:

  1. Socket accepting. It's well covered by rotor_stream::Accept, and even if you implement it by hand I believe it's better to accept next connection in spawned() rather than wait for next level-triggered event. While is it the best way or not depends on many things, I want it to be a deliberate decision, rather than default.
  2. Establishing client connections. If you have a connection pool state machine which spawns client connections, there is nothing that ensures that maximum single connection can be created per wake up of connection pool.
  3. The only case with ok() I have is in rotor-carbon, which is a monitoring protocol, which have an inherently single connection

The (3) looks more like exception rather than rule. There are many more cases that does have unreachable!() in spawned rather than ok().

The timeout and wakeup are also deliberately non-defaulted. In my perspective, almost nobody will use rotor::Machine in end-user application. It's more suited for protocol writers. And for writing another protocol on top of rotor:Machine you must deliberately choose if you want to skip timeouts and wakeups. Most protocols should provide timeout and wakeup in the handler based on top of it, so user can use asynchronous things in handler. Off the top of my head, I think only unidirectional protocols might ignore the events.

The spawned case is also similar, only protocol writers will need to write it, not the protocol users, so I believe it is better to enforce a decision. Ignoring the is easy. But unawareness of these things may lead to ugly workarounds.

Does it make sense?

seanmonstar commented 8 years ago

Yes, that makes sense. I agree, I don't expose Machine to a user, but instead a server::Handler that is ignorant of the internals.