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

The source's "domain" is ignored in jetstream.update_stream #1350

Open
zerolfx opened this issue Dec 17, 2024 · 4 comments
Open

The source's "domain" is ignored in jetstream.update_stream #1350

zerolfx opened this issue Dec 17, 2024 · 4 comments
Labels
defect Suspected defect such as a bug or regression

Comments

@zerolfx
Copy link

zerolfx commented Dec 17, 2024

Observed behavior

After updating the stream with an external source, run nats stream report, the API Prefix field is empty, and Error field contains stream not found (10059).

This problem also exists in nats.go.

A possible cause:
There is domain-related logic in create_stream function, but not in update_stream.

if let Some(ref mut sources) = config.sources {
for source in sources {
if let Some(ref mut domain) = source.domain {
if source.external.is_some() {
return Err(CreateStreamError::new(
CreateStreamErrorKind::DomainAndExternalSet,
));
}
source.external = Some(External {
api_prefix: format!("$JS.{domain}.API"),
delivery_prefix: None,
})
}
}
}

pub async fn update_stream<S>(&self, config: S) -> Result<Info, UpdateStreamError>
where
S: Borrow<Config>,
{
let config = config.borrow();
if config.name.is_empty() {
return Err(CreateStreamError::new(
CreateStreamErrorKind::EmptyStreamName,
));
}
if !is_valid_name(config.name.as_str()) {
return Err(CreateStreamError::new(
CreateStreamErrorKind::InvalidStreamName,
));
}
let subject = format!("STREAM.UPDATE.{}", config.name);
match self.request(subject, config).await? {
Response::Err { error } => Err(error.into()),
Response::Ok(info) => Ok(info),
}
}

Expected behavior

The API Prefix is correctly set to $JS.xxxx.API.

Server and client version

server: 2.10.23
client: 0.37.0

Host environment

No response

Steps to reproduce

No response

@zerolfx zerolfx added the defect Suspected defect such as a bug or regression label Dec 17, 2024
@Jarema
Copy link
Member

Jarema commented Dec 27, 2024

Hey!

Thanks for the report.
I'm working on this one.

@Jarema
Copy link
Member

Jarema commented Dec 27, 2024

I cannot reproduce this.

here is a simple (and ugly) test:

    #[tokio::test]
    async fn stream_update_external() {
        let server = nats_server::run_server("tests/configs/jetstream.conf");
        let client = async_nats::connect(server.client_url()).await.unwrap();

        let jetstream = async_nats::jetstream::new(client);

        jetstream
            .create_stream(stream::Config {
                name: "origin".to_string(),
                subjects: vec!["origin.>".to_string()],
                ..Default::default()
            })
            .await
            .unwrap();

        let mut stream = jetstream
            .create_stream(stream::Config {
                name: "events".to_string(),
                subjects: vec!["events.>".to_string()],
                ..Default::default()
            })
            .await
            .unwrap();

        jetstream
            .update_stream(stream::Config {
                name: "events".to_string(),
                subjects: vec!["events.>".to_string()],
                sources: Some(vec![stream::Source {
                    name: "origin".to_string(),
                    external: Some(External {
                        api_prefix: "API.PREFIX".to_string(),
                        ..Default::default()
                    }),
                    ..Default::default()
                }]),
                ..Default::default()
            })
            .await
            .unwrap();

        assert_eq!(
            stream
                .info()
                .await
                .unwrap()
                .config
                .sources
                .as_ref()
                .unwrap()[0]
                .external
                .as_ref()
                .unwrap()
                .api_prefix,
            "API.PREFIX"
        );
    }

Please keep in mind that the external is NOT a domain, but the full prefix.

@zerolfx
Copy link
Author

zerolfx commented Dec 31, 2024

I may not have stated the problem clearly. The external field works when updating a stream, but the domain does not.

Here is the example code:

    #[tokio::test]
    async fn stream_update_external() {
        let client = async_nats::connect_with_options(
            "localhost:4222",
            async_nats::ConnectOptions::default()
                .retry_on_initial_connect()
                .user_and_password("user".to_string(), "user".to_string()),
        )
        .await
        .unwrap();

        let js = async_nats::jetstream::new(client);
        
        let _ = js.delete_stream("test").await;

        let mut stream = js
            .create_stream(stream::Config {
                name: "test".into(),
                sources: Some(vec![stream::Source {
                    name: "source".into(),
                    domain: Some("domain".into()),
                    ..Default::default()
                }]),
                ..Default::default()
            })
            .await
            .unwrap();

        let stream_info = stream.info().await.unwrap();
        assert_eq!(
            stream_info.config.sources.as_ref().unwrap()[0]
                .external
                .as_ref()
                .unwrap()
                .api_prefix,
            "$JS.domain.API"
        );

        js.update_stream(stream::Config {
            sources: Some(vec![stream::Source {
                name: "source".into(),
                domain: Some("domain2".into()),
                ..Default::default()
            }]),
            ..stream_info.config.clone()
        }).await.unwrap();

        let stream_info = stream.info().await.unwrap();
        assert_eq!(
            stream_info.config.sources.as_ref().unwrap()[0]
                .external
                .as_ref()
                .unwrap()
                .api_prefix,
            "$JS.domain2.API"
        );
    }

@Jarema
Copy link
Member

Jarema commented Dec 31, 2024

yes, this is correct.

Please, as a workaround, use external.
To be fair I do not like how the structure is handled, as domain is a utility for setting whole prefix by just specifying the domain, which is purely client side here.

I will think how to address it in the best way.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
defect Suspected defect such as a bug or regression
Projects
None yet
Development

No branches or pull requests

2 participants