Giter VIP home page Giter VIP logo

Comments (14)

gathuku avatar gathuku commented on August 31, 2024 1

I would like to see this feature implemented. Right now you can delay each delivery method with delay option.
@excid3 can we have something like delay_until: Date.tomorrow.noon, but i would like this be set when sending the notifications so it can delay all the notifications methods.

Currently trying to implement something like this , i think it will be a bit easier if there was delay_until

  def perform
    Reminder.for_each do |reminder| 
      # to_be_sent_at less that 1 hour
      if reminder.to_be_sent_at < 1.hour.from_now 
        delay = (reminder.to_be_sent_at - Time.current).minutes
        PaymentReminder.with(borrowing: reminder.borrowing, delay: delay).deliver(reminder.borrowing.user)
      end
    end
  end

from noticed.

ykamin-booth avatar ykamin-booth commented on August 31, 2024 1

I guess I didn't realize this feature had not been implemented. I had been using the standard ActiveJobs delay method with DelayedJobs with no issues:
MessageNotification.with(message: message).delay(run_at: Time.now+15.seconds).deliver(recipients)

However, now that I moved to Sidekiq I'm getting a NoMethod error when I try to do this (despite enabling the delay method for Sidekiq in my initializer).
NoMethodError: undefined method 'delay' for #<MessageNotification:0x00007f1930f7be58>

Is this expected? Why would there be different behavior here?

My use case for delaying the entire notification is in a chat where if the other person is in the chat and reads the message, there shouldn't be a notification at all (both in terms of cluttering up the list of notifications on the index page and in terms of seeing the new notification come in over actioncable).

from noticed.

excid3 avatar excid3 commented on August 31, 2024

Currently we have a single method for delivering:

        # Always perfrom later if a delay is present
        if (delay = delivery_method.dig(:options, :delay))
          method.set(wait: delay).perform_later(args)
        elsif enqueue
          method.perform_later(args)
        else
          method.perform_now(args)
        end

We could combine the delivery method delay with a set(wait:) in order to support notifications with multiple delivery methods.

For example:

class NewComment < Noticed::Base
  deliver_by :database
  deliver_by :slack
  deliver_by :email, delay: 5.minutes
end
NewComment.with(comment: @comment).set(wait: 15.minutes).deliver_later

The database delivery method should run immediately (so the other delivery methods can access the database record).
The slack delivery method should run in 15 minutes.
The email delivery method should run in 20 minutes.

We should also support wait_until:

NewComment.with(comment: @comment).set(wait_until: 15.minutes.from_now).deliver_later

Question:
What happens if set(wait: 5.minutes, wait_until: 10.minutes.from_now) is used? Does one take precedence in ActiveJob?
Answer:
wait_until takes precedence

from noticed.

rbague avatar rbague commented on August 31, 2024

Answering your question, yes, wait_until takes precedence over wait as you can see here.

But setting a delay on the notification brings an issue with the database delivery, which I encountered while working on #61. The database delivery must be executed immediately, it can not be enqueued, otherwise, the database record won't be available for the other deliveries, as run_delivery_method here would return the scheduled job instead of the database record.

I am working on adding documentation, as well as adding some tests for it since I found the issue. I hope to have a PR soon.

from noticed.

excid3 avatar excid3 commented on August 31, 2024

Thanks for checking on wait_until 👍

We do have an exception for database delivery so it runs immediately no matter what. I'll update my example to use a different delivery method to clarify that.

from noticed.

excid3 avatar excid3 commented on August 31, 2024

It looks like we might be running the database delivery method twice though because it's not removed from the delivery methods on line 81.

delivery_methods.each do |delivery_method|

That's definitely a bug we should fix.

from noticed.

rbague avatar rbague commented on August 31, 2024

Sorry, my bad. What I meant here is that the database delivery can't be delayed as it won't return the database record, I realized this after merging the PR. That is what I was working on

But setting a delay on the notification brings an issue with the database delivery, which I encountered while working on #61. The database delivery must be executed immediately, it can not be enqueued, otherwise, the database record won't be available for the other deliveries, as run_delivery_method here would return the scheduled job instead of the database record.

And regarding the issue you just commented, it seems to be working right in my machine, the database delivery is only executed once and removed from the delivery_methods array.

from noticed.

excid3 avatar excid3 commented on August 31, 2024

Oh yeah, I just glossed over the delete line there. It does remove it.

That's fine if database delivery is the exception. It always will be for that reason.

from noticed.

gathuku avatar gathuku commented on August 31, 2024

Hey @excid3 , I gave this a try but am having problems.

What i implemented

module Noticed
class Base
   class_attribute :set_options, instance_writer: true, default: {}
   
   class << self 
   end

   def set(options)
     set_options = options
     self
   end

end
end

This allowed to set the options required , which is stored in class_attribute set_options

CommentNofication.with(foo: :bar).set(wait: 3.minutes, wait_until: Date.tomorrow.noon, priority: 10)

when i come to delivering i added another elseif which checks if set_options has wait_until and set it in method.

        # Always perfrom later if a delay is present
        if (delay = delivery_method.dig(:options, :delay))
          method.set(wait: delay).perform_later(args)
        elsif(wait_until = set_options.dig(:wait_until))
            method.set(wait_until: wait_until).perform_later(args)
        elsif enqueue
          method.perform_later(args)
        else
          method.perform_now(args)
        end

This implementation results to ActiveJob::SerializationError: Unsupported argument type: Noticed::DeliveryMethods::Database on delivering notification . ref

ExampleNotification.with(foo: :bar).set(wait_until: Date.tomorrow.noon).deliver(user)

cc @rbague

from noticed.

rbague avatar rbague commented on August 31, 2024

Hi @gathuku. The error you are seeing is because the database delivery is being enqueued instead of being executed right away. Thus making this line return the enqueued job (Noticed::DeliveryMethods::Database - which can't be serialized by active_job) instead of the database record, as the code expects. There should be a failing test to ensure this doesn't happen.

The database delivery should always be executed with perform_now regardless of which options are passed to ensure that the database record is always accessible by the other delivery methods

from noticed.

gathuku avatar gathuku commented on August 31, 2024

Thank you @rbague

from noticed.

dvodvo avatar dvodvo commented on August 31, 2024

Chiming in late here (possibly). wait_until seems to reference a delay. Does/can it apply to a set datetime?

An existing workflow would be to launch a whenever schedule action and call the mailer, Twilio issuance engine, whatever. If I am not mistaken, with noticed I would have to generate a Custom Delivery Method and hook it into some scheduling mechanism. Which is possibly more complex than the existing workflow. This is then compounded by the fact that other cases are much simpler with noticed thus leading to establishing both mechanisms, which is unduly complex.

from noticed.

gathuku avatar gathuku commented on August 31, 2024

@ykamin-booth i think delay is an delayed_job specific method so when you switch to sidekiq you can't use the method.
I think you want to achieve fallback notifications https://github.com/excid3/noticed#fallback-notifications

from noticed.

ykamin-booth avatar ykamin-booth commented on August 31, 2024

Because I set Sidekiq::Extensions.enable_delay! in my sidekiq initializer, I should still be able to use the method (https://github.com/mperham/sidekiq/wiki/Delayed-extensions). I have tested this with other classes and instance methods and was able to use it--it's only in Noticed notifications that I'm getting this NoMethod error.

Fallback notifications wouldn't work in this use case unless I just had some kind of wrapper notification that was never visible to its recipients, because the point is that I don't want the notification to even hit the database if the message is read:
deliver_by :database, unless: :message_read?

from noticed.

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.