Git Product home page Git Product logo

Comments (6)

MTRNord avatar MTRNord commented on June 14, 2024 1

Hm turns out apart from systemd actually using SIGTERM not SIGINT the lock() actually gets never free. So the cleanup never happens and it just gets stuck until systemd does SIGKILL :D

Edit: working on fixing this in the above code

from yaque.

tokahuke avatar tokahuke commented on June 14, 2024

Hum... I think that, in your case, it would be best receiver were behind a Mutex and you spawned a task in tokio specifically to handle ctrl+c. This allows you to break up concerns ("handle signal" vs. "receive message") a bit better.

However, you can make this work in the current code putting receiver behind a RefCell. We know that no two mutable references will exist in runtime, so just move the borrow checking to runtime.

Tell me which approach happens to solve it for you!

from yaque.

MTRNord avatar MTRNord commented on June 14, 2024

I didnt test this yet but it compiles. I am also not entirely sure yet which way around I want the tokio::spawn and loop. :D Either could run in the tokio thread. In the end it probably doesn't matter too much here.

match receiver {
        Ok(receiver) => {
            let receiver = Arc::new(Mutex::new(receiver));
            let receiver_clone = Arc::clone(&receiver);

            tokio::spawn(async move {
                tokio::signal::ctrl_c()
                    .await
                    .expect("failed to listen for ctrl-c event");
                info!("Received ctr-c. Cleaning up");
                receiver_clone
                    .lock()
                    .await
                    .save()
                    .expect("Unable to save queue");
                exit(0);
            });

            loop {
                let mut receiver_lock = receiver.lock().await;
                let data = receiver_lock.recv().await;

                match data {
                    Ok(data) => {
                        let email_bytes = &*data;
                        let email_json = serde_json::from_slice::<EmailPayload>(email_bytes)?;

                        if let Err(e) = send_email_job(&email_json).await {
                            tracing::error!(
                                "Error while sending email: {:?}. Adding it to the queue again",
                                e
                            );
                            // FIXME: This can race the lock leading to an error. We should
                            //        probably handle this better.
                            let mut sender = Sender::open(config.task_folder.clone())?;
                            let json_bytes = serde_json::to_vec(&email_json)?;
                            sender.send(json_bytes).await?;
                        }
                        // Mark the job as complete
                        data.commit()?;
                    }
                    Err(e) => {
                        tracing::error!("Error while receiving data from receiver: {:?}", e);
                    }
                }
            }
        }
        Err(e) => {
            error!("Unable to open receiver: {:?}. Giving up.", e);
            Ok(())
        }
    }

I will close this when I confirmed that this actually runs too :) Thanks for the help!

from yaque.

MTRNord avatar MTRNord commented on June 14, 2024

Ooops just realised that I was blocking on the receivers.recv() "forever". So that will obviously cause issues.

I went with this solution now:

https://github.com/erooster-mail/erooster/blob/bb0133ec579cc0074ded6d6f1d794db1c01382d1/crates/erooster_smtp/src/servers/mod.rs#L92-L168

That seems to work nicely :)

from yaque.

tokahuke avatar tokahuke commented on June 14, 2024

You are welcome!

from yaque.

tokahuke avatar tokahuke commented on June 14, 2024

Oh, BTW... https://github.com/erooster-mail/erooster/blob/bb0133ec579cc0074ded6d6f1d794db1c01382d1/crates/erooster_smtp/src/servers/mod.rs#L103 you can use Receiver::recv_timeout here instead.

from yaque.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.