Skip to content
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

Tech debt #64

Merged
merged 22 commits into from
Sep 1, 2024
Merged

Tech debt #64

merged 22 commits into from
Sep 1, 2024

Conversation

rustworthy
Copy link
Collaborator

@rustworthy rustworthy commented May 20, 2024

Threads that needed to be addressed after the recent "async" PR merge:


This change is Reviewable

Copy link

codecov bot commented May 20, 2024

Codecov Report

Attention: Patch coverage is 32.35294% with 115 lines in your changes missing coverage. Please review.

Project coverage is 67.1%. Comparing base (a63b658) to head (1227381).
Report is 23 commits behind head on main.

Files with missing lines Patch % Lines
src/tls/rustls.rs 0.0% 30 Missing ⚠️
src/tls/native_tls.rs 0.0% 28 Missing ⚠️
src/proto/client/ent.rs 0.0% 17 Missing ⚠️
src/worker/builder.rs 57.5% 14 Missing ⚠️
src/proto/single/ent/cmd.rs 0.0% 12 Missing ⚠️
src/proto/mod.rs 62.5% 3 Missing ⚠️
src/proto/single/ent/progress.rs 0.0% 3 Missing ⚠️
src/worker/stop.rs 0.0% 3 Missing ⚠️
src/proto/batch/handle.rs 0.0% 2 Missing ⚠️
src/worker/mod.rs 91.3% 2 Missing ⚠️
... and 1 more
Additional details and impacted files
Files with missing lines Coverage Δ
src/proto/client/mod.rs 86.8% <100.0%> (ø)
src/proto/single/ent/mod.rs 100.0% <ø> (ø)
src/worker/health.rs 88.6% <ø> (ø)
src/proto/batch/status.rs 0.0% <0.0%> (ø)
src/proto/batch/handle.rs 0.0% <0.0%> (ø)
src/worker/mod.rs 83.4% <91.3%> (+<0.1%) ⬆️
src/proto/mod.rs 72.7% <62.5%> (-27.3%) ⬇️
src/proto/single/ent/progress.rs 0.0% <0.0%> (ø)
src/worker/stop.rs 54.5% <0.0%> (-20.5%) ⬇️
src/proto/single/ent/cmd.rs 0.0% <0.0%> (ø)
... and 4 more

@rustworthy
Copy link
Collaborator Author

As for the boxed dyn Connection thread, please see this comment

@rustworthy rustworthy requested a review from jonhoo May 20, 2024 08:21
@jonhoo
Copy link
Owner

jonhoo commented May 25, 2024

For the Box<dyn Connection> bit, I think the trick is going to be to make Reconnect also return a Box<dyn Connection>. That should make it object safe!

@rustworthy rustworthy marked this pull request as draft June 8, 2024 04:53
@rustworthy
Copy link
Collaborator Author

rustworthy commented Jul 6, 2024

For the Box<dyn Connection> bit, I think the trick is going to be to make Reconnect also return a Box<dyn Connection>. That should make it object safe!

That actually did the trick. We've been able to get rid of the S generic, please have a look at this.

EDIT: the flaky test should be fixed by #71

@rustworthy rustworthy marked this pull request as ready for review July 6, 2024 10:42
Copy link
Owner

@jonhoo jonhoo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm loving this set of changes!

) -> Result<Worker<E>, Error>
where
S: AsyncRead + AsyncWrite + Send + Sync + Unpin + 'static,
BufStream<S>: Reconnect,
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think if we have a blanket implementation of Reconnect for BufStream<S> where S: Reconnect it should be sufficient to add Reconnect to the bounds on S

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ditto for Client::connect_with

Copy link
Collaborator Author

@rustworthy rustworthy Aug 3, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the thing with Reconnect is that Box<dyn Connection> returned from async fn reconnect() should already be AsyncBufRead. So we are accepting any S that is AsyncRead + AsyncWrite + Send + Sync + Unpin + 'static' because we then buffer it making it AsyncBufRead which only then qualifies it as Reconnect

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, hmm, I think we might need two traits here then:

trait Reconnect {
    fn reconnect(&mut self) -> io::Result<BoxedConnection>;
}
trait UnbufferedConnection: AsyncRead + AsyncWrite + Send + Sync + Unpin + 'static + ReconnectUnbuffered {}
impl<T> UnbufferedConnection for T where T: AsyncRead + AsyncWrite + Send + Sync + Unpin + 'static {}
trait ReconnectUnbuffered {
    fn reconnect(&mut self) -> io::Result<Box<dyn UnbufferedConnection>>;
}

with

impl<S> Reconnect for BufStream<S> where S: UnbufferedConnection {}

it's not super pretty, but it would allow folks to bring their own buffered or unbuffered connection types, and use the former directly or use the latter wrapped in a BufStream.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am afraid I am not following here.

For both Client::connect_with and WorkerBuilder::connect_with the bound is now:

S: AsyncBufRead + AsyncWrite + Reconnect + Send + Sync + Unpin + 'static,

Copy link
Owner

@jonhoo jonhoo Sep 1, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think maybe I've led you astray. I read over the code again this morning, and I think I understand what you've been trying to tell me 😅 I think the only thing left that's confusing to me is how we can have

impl<S> Reconnect for BufStream<S>

and also

impl Reconnect for BufStream<TlsStream<tokio::net::TcpStream>>

and

impl Reconnect for BufStream<TlsStream<proto::BoxedConnection>>

It feels like that first impl should overlap with the other two. I'm guessing it doesn't because we define Reconnect ourselves and we don't have

impl Reconnect for TlsStream<tokio::net::TcpStream>

or

impl Reconnect for TlsStream<proto::BoxedConnection>

That makes me wonder though — would it be sufficient to instead have

impl Reconnect for TlsStream<S>

(where I don't think we even need to require AsyncBufRead for that S)?

It also feels weird that we even have

impl Reconnect for BufStream<TlsStream<proto::BoxedConnection>>

Because that suggests we may end up double-buffering (since BoxedConnection is already AsyncBufRead).

src/worker/builder.rs Outdated Show resolved Hide resolved
src/tls/rustls.rs Show resolved Hide resolved
src/tls/rustls.rs Show resolved Hide resolved
src/tls/rustls.rs Show resolved Hide resolved
src/proto/single/ent/progress.rs Show resolved Hide resolved
src/proto/single/ent/cmd.rs Show resolved Hide resolved
src/proto/mod.rs Show resolved Hide resolved
src/proto/client/ent.rs Outdated Show resolved Hide resolved
@rustworthy
Copy link
Collaborator Author

@jonhoo Sorry for thrashing the loop 😅

Please have another look at this PR. I think I've addressed almost all the threads, and will need your advice in a couple of them.


Something I've noticed, but would like to discuss with you first:

  • Job's reserve_for can be Duration

  • What do you make of handler accepting something which is Into<Job>? This way we could for example supply a macro that will implement Into<Job> for something that is Serialize . Just thinking about the future :)

  • Worker should probably have a Worker::is_terminated method being publicly available, so that they can check if they can safely re-run it.

  • We could use tokio's interval in the heartbeat thread when we are checking the state every 100 millis. That's a nit, but maybe a more idiomatic variant.

@rustworthy rustworthy requested a review from jonhoo August 9, 2024 14:48
tests/real/community.rs Outdated Show resolved Hide resolved
src/worker/mod.rs Outdated Show resolved Hide resolved
Cargo.toml Outdated Show resolved Hide resolved
.await
.unwrap()
.enqueue(Job::builder("panic").queue(local).build())
let mut c = Client::connect(None).await.unwrap();
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The more I look at connect(None), the less I like it. I wonder if we should have two methods:

fn connect() { .. }
fn connect_to(addr: &str) { .. }

what do you think?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the suggested changes will make the bindings more ergonomic, because now even though they are already providing FAKTORY_URL into the environment, we still make them pass None to the the Client::connect.

What do you make of batching these changes with my earlier suggestions in a follow-up "polishing" PR? Also what do you make of those suggestions?

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I'm fine doing that change in a separate PR — this one is already growing quite large and unwieldy! I should have used reviewable from the start for it :p

) -> Result<Worker<E>, Error>
where
S: AsyncRead + AsyncWrite + Send + Sync + Unpin + 'static,
BufStream<S>: Reconnect,
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, hmm, I think we might need two traits here then:

trait Reconnect {
    fn reconnect(&mut self) -> io::Result<BoxedConnection>;
}
trait UnbufferedConnection: AsyncRead + AsyncWrite + Send + Sync + Unpin + 'static + ReconnectUnbuffered {}
impl<T> UnbufferedConnection for T where T: AsyncRead + AsyncWrite + Send + Sync + Unpin + 'static {}
trait ReconnectUnbuffered {
    fn reconnect(&mut self) -> io::Result<Box<dyn UnbufferedConnection>>;
}

with

impl<S> Reconnect for BufStream<S> where S: UnbufferedConnection {}

it's not super pretty, but it would allow folks to bring their own buffered or unbuffered connection types, and use the former directly or use the latter wrapped in a BufStream.

@rustworthy rustworthy requested a review from jonhoo August 18, 2024 16:16
Copy link
Owner

@jonhoo jonhoo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm going to approve and land this just so we can hone the discussion (in a separate PR) specifically onto the one remaining question around the Reconnect impls. I still think we need to nail it down before an eventual release.

@jonhoo jonhoo merged commit 3c4058a into main Sep 1, 2024
17 of 19 checks passed
@rustworthy rustworthy deleted the chore/tech-debt branch September 19, 2024 17:52
@rustworthy rustworthy mentioned this pull request Sep 19, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants