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

feat: Implement Sourcer traits for serving source #2301

Merged
merged 18 commits into from
Jan 6, 2025
Merged

Conversation

BulkBeing
Copy link
Contributor

closes: #2281

@vigith
Copy link
Member

vigith commented Dec 24, 2024

please resolve conflicts?

Copy link

codecov bot commented Dec 24, 2024

Codecov Report

Attention: Patch coverage is 86.10662% with 86 lines in your changes missing coverage. Please review.

Project coverage is 67.11%. Comparing base (0c86e82) to head (1dcad81).
Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
rust/serving/src/source.rs 90.32% 18 Missing ⚠️
rust/numaflow-core/src/shared/create_components.rs 0.00% 17 Missing ⚠️
rust/numaflow-core/src/source/serving.rs 90.90% 13 Missing ⚠️
rust/numaflow-core/src/source.rs 0.00% 7 Missing ⚠️
rust/serving/src/config.rs 78.78% 7 Missing ⚠️
rust/numaflow-core/src/config/components.rs 0.00% 6 Missing ⚠️
rust/serving/src/pipeline.rs 0.00% 5 Missing ⚠️
rust/numaflow-core/src/message.rs 0.00% 4 Missing ⚠️
rust/serving/src/app/jetstream_proxy.rs 97.08% 4 Missing ⚠️
rust/serving/src/app.rs 95.45% 3 Missing ⚠️
... and 1 more
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2301      +/-   ##
==========================================
+ Coverage   67.08%   67.11%   +0.02%     
==========================================
  Files         349      351       +2     
  Lines       45055    45263     +208     
==========================================
+ Hits        30227    30378     +151     
- Misses      13756    13818      +62     
+ Partials     1072     1067       -5     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@BulkBeing BulkBeing force-pushed the serving-sourcer-traits branch from 824ae59 to 76c2371 Compare January 2, 2025 07:48
@BulkBeing BulkBeing marked this pull request as ready for review January 2, 2025 07:48
Copy link
Member

@vigith vigith left a comment

Choose a reason for hiding this comment

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

Why is the test coverage too low?

rust/Cargo.toml Outdated
@@ -40,8 +40,8 @@ verbose_file_reads = "warn"
# This profile optimizes for runtime performance and small binary size at the expense of longer build times.
# Compared to default release profile, this profile reduced binary size from 29MB to 21MB
# and increased build time (with only one line change in code) from 12 seconds to 133 seconds (tested on Mac M2 Max).
[profile.release]
lto = "fat"
# [profile.release]
Copy link
Member

Choose a reason for hiding this comment

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

no longer valid?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Reverted. Had commented it out for faster image builds on laptop.

@@ -37,7 +38,7 @@ pub(crate) mod source {
Generator(GeneratorConfig),
UserDefined(UserDefinedConfig),
Pulsar(PulsarSourceConfig),
Serving(serving::Settings),
Serving(Arc<serving::Settings>),
Copy link
Member

Choose a reason for hiding this comment

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

why Arc, is it for easy cloning? how come this is different from the rest? please document the reason?

@@ -55,6 +55,7 @@ mod tracker;
mod mapper;

pub async fn run() -> Result<()> {
let _ = rustls::crypto::aws_lc_rs::default_provider().install_default();
Copy link
Member

Choose a reason for hiding this comment

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

what is this for? please document

SourceType::Serving(_) => {
unimplemented!("Serving as built-in source is not yet implemented")
SourceType::Serving(config) => {
let serving = ServingSource::new(Arc::clone(config), batch_size, read_timeout).await?;
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
let serving = ServingSource::new(Arc::clone(config), batch_size, read_timeout).await?;
let serving = ServingSource::new(config, batch_size, read_timeout).await?;

why clone, can't we give the ownership?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The match is on a reference, so the config here is a &Arc<Settings>.

let offset = Offset::String(StringOffset::new(message.id.clone(), 0));

Ok(Message {
keys: Arc::from(vec![]),
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
keys: Arc::from(vec![]),
// we do not support keys from HTTP client
keys: Arc::from(vec![]),

}

fn partitions(&self) -> Vec<u16> {
vec![]
Copy link
Member

Choose a reason for hiding this comment

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

we should have atleast one partition?

}

impl super::SourceAcker for ServingSource {
async fn ack(&mut self, offsets: Vec<Offset>) -> Result<()> {
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
async fn ack(&mut self, offsets: Vec<Offset>) -> Result<()> {
/// HTTP response is sent only once we have confirmation that the message has been written to the ISB.
async fn ack(&mut self, offsets: Vec<Offset>) -> Result<()> {

}
}

impl super::SourceAcker for ServingSource {
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
impl super::SourceAcker for ServingSource {
// TODO: implement for async and sync, currently it is only for async
impl super::SourceAcker for ServingSource {

},
};

proxy_state.message.send(message).await.unwrap(); // FIXME:
Copy link
Member

Choose a reason for hiding this comment

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

FIXME :)

Signed-off-by: Vigith Maurice <[email protected]>
Comment on lines 52 to 54
) -> Result<()> {
let (messages_tx, messages_rx) = mpsc::channel(10000);
// Create a redis store to store the callbacks and the custom responses
Copy link
Contributor

Choose a reason for hiding this comment

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

10000 is way too much, should we restrict it to 2 * batch size?

Comment on lines 65 to 80
tokio::spawn(async move {
let mut serving_actor = ServingSourceActor {
messages: messages_rx,
handler_rx,
tracker: HashMap::new(),
};
serving_actor.run().await;
});
let app = crate::AppState {
message: messages_tx,
settings,
callback_state,
};
tokio::spawn(async move {
crate::serve(app).await.unwrap();
});
Copy link
Contributor

Choose a reason for hiding this comment

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

make sure these tokio tasks are aborted during shutdown, structured concurrency :).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This might need more work. Created an issue for it #2309

Comment on lines 40 to 46
}

struct ServingSourceActor {
messages: mpsc::Receiver<MessageWrapper>,
handler_rx: mpsc::Receiver<ActorMessage>,
tracker: HashMap<String, oneshot::Sender<()>>,
}
Copy link
Contributor

Choose a reason for hiding this comment

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

doc

Comment on lines 106 to 109

async fn read(&mut self, count: usize, timeout_at: Instant) -> Vec<Message> {
let mut messages = vec![];
loop {
Copy link
Contributor

Choose a reason for hiding this comment

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

return Result<Vec<Message>> to fix the FIXME :). Source reader trait returns a result.

Comment on lines +110 to +112
if messages.len() >= count || Instant::now() >= timeout_at {
break;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

document

Comment on lines 134 to 137
let offset = offset
.strip_suffix("-0")
.expect("offset does not end with '-0'"); // FIXME: we hardcode 0 as the partition index when constructing offset
let confirm_save_tx = self
Copy link
Contributor

Choose a reason for hiding this comment

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

use vertex replica as the partition index incase of source.

Comment on lines 162 to 163
let (actor_tx, actor_rx) = mpsc::channel(1000);
ServingSourceActor::start(settings, actor_rx).await?;
Copy link
Contributor

Choose a reason for hiding this comment

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

make the channel size configurable, it can be 2 * batch size.

Comment on lines 33 to 35
timeout_at: Instant,
reply_to: oneshot::Sender<Vec<Message>>,
},
Copy link
Contributor

Choose a reason for hiding this comment

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

make oneshot sender return Result, to handle critical errors?

},
Ack {
offsets: Vec<String>,
reply_to: oneshot::Sender<()>,
Copy link
Contributor

Choose a reason for hiding this comment

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

same here, make oneshot sender return Result?

Signed-off-by: Sreekanth <[email protected]>
Comment on lines 121 to 123
// Stop if the read timeout has reached or if we have collected the requested number of messages
if messages.len() >= count || Instant::now() >= timeout_at {
break;
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we use ReceiverStream instead of mpsc channel to store the messages? That way you can chunk the stream using chunks_timeout()?

Copy link
Contributor Author

@BulkBeing BulkBeing Jan 6, 2025

Choose a reason for hiding this comment

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

I can't use ReceiverStream here since chunks_timeout consumes self. This results in:

cannot move out of `self.messages` which is behind a mutable reference

ReceiverStream.chunks_timeout() would have worked if it was function that accepts the ReceiverStream and uses it in a loop{} to consume it. In this case, the Receiver end is a struct member.

Comment on lines 130 to 131
// The error will happen on all the subsequent read attempts too.
if messages.is_empty() {
Copy link
Contributor

Choose a reason for hiding this comment

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

Why do we need to send an error when we don't have any messages?

Copy link
Contributor Author

@BulkBeing BulkBeing Jan 6, 2025

Choose a reason for hiding this comment

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

If the code reaches here, all the Senders are already dropped. Any subsequent read requests also will fail.
Unless there is some bug, this code path should never reach.

Copy link
Contributor

@yhl25 yhl25 left a comment

Choose a reason for hiding this comment

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

LGTM!

@yhl25 yhl25 merged commit 8d8340c into main Jan 6, 2025
28 checks passed
@yhl25 yhl25 deleted the serving-sourcer-traits branch January 6, 2025 05:57
SaniyaKalamkar pushed a commit to SaniyaKalamkar/numaflow that referenced this pull request Jan 19, 2025
Signed-off-by: Sreekanth <[email protected]>
Signed-off-by: Vigith Maurice <[email protected]>
Co-authored-by: Vigith Maurice <[email protected]>
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.

Implement Sourcer traits to support serving
3 participants