wisper
A micro library providing Ruby objects with Publish-Subscribe capabilities
I have wisper listeners in the app/listeners directory.
I also have the /config/initializers/wisper.rb
module Wisper
def self.setup
configure do |config|
config.broadcaster(:default, Broadcasters::LoggerBroadcaster.new(Rails.logger, Broadcasters::SendBroadcaster.new))
end
end
end
Wisper.setup
Wisper.subscribe(ProjectListener.new)
Wisper.subscribe(FeedListener.new)
Can I somehow force Rails to reload the Listeners at every request?
Source: (StackOverflow)
I have a project which used wisper https://github.com/krisleech/wisper to provide publisher and subscribers functionalities. The gem works perfectly under development and production modes. However, when I try to add some tests for them (rake test:integration), the newly added tests refused to work. The publisher (maybe also the listener) in the tests mode stopped working anymore.
Core::Request.subscribe(Listener::Studentlistener, async: true)
Core::Request.subscribe(Listener::Tutorlistener, async: true)
I used the sidekiq as a async backend, i used wisper-sidekiq gem to handle the async requests, not sure if this would be the problem?
,puma as the server, MRI ruby 2.0.0
Do I have to a set up something in order for the test to run?
it "Student can get latest status after looking for xxx tutor" do
post api_v1_students_request_look_for_xxx_tutor_path,
{ subject: 'nothing' },
{ "AUTHORIZATION" => "xxx"}
expect(response).to be_success
get api_v1_students_status_path, nil,
{ "AUTHORIZATION" => "xxx"}
expect(response).to be_success
json_response = JSON.parse(response.body)
expect(json_response['state']).to eq('matching')
end
The listener should receive the publishing between these two posts and update the state to be "matching". However, now when I run rspec the test failed because the publisher never publish anything and hence the state is not updated correctly.
Source: (StackOverflow)
I'm trying to make a small example with wisper-sidekiq gem. The queue is created, but it does not start. Why? I will describe the steps that you are doing, I think it will be easier. I hope for your help.
A. controller:
class BooksController < ApplicationController
def create
service = CreateBook.new
service.subscribe(ActivityListener, async: true)
service.on(:reserver_item_successfull) { |book| redirect_to book_path(book.id) }
service.on(:reserver_item_failed) { |book| @book = Book.new(book_params); respond_with(@book) }
service.execute(current_user, book_params)
end
B. service:
require 'wisper/sidekiq'
require 'sidekiq/api'
class CreateBook
include Wisper::Publisher
def execute(performer, attributes)
book = Book.new(attributes)
if book.valid?
book.save
broadcast(:reserver_item_successfull, performer, book)
else
broadcast(:book_failed, performer, book)
end
end
end
C. listener:
class ActivityListener
def self.reserver_item_successfull(performer, book)
puts performer.name.to_s + ", book: " + book.title.to_s
end
end
When I save the book, then of course creates a queue. But:
- sidekiq silent (the logs are empty, but the queue was created)
- redis silent too
Maybe I'm wrong start redis (redis-server) or sidekiq (bundle exec sidekiq)? Please help me.
P.S. Try bundle exec sidekiq -d -e production sidekiq -q default -C config/sidekiq.yml, but not result. The sidekiq.rb empty.
Source: (StackOverflow)
I'm trying to figure out how to use wisper with Devise.
When a new user account is registered, I want to create some sample data for that user.
So in my user model I would have:
include Wisper::Publisher
after_create :notify
def notify
publish(:user_created, self)
end
and my listener would be something like:
class SampleDataCreator
def user_created(user)
user.widgets.create!(name: "Your First Widget")
end
end
But I can't figure out how to tie this into Devise. How can I configure the SampleDataCreator
to listen for events from the Devise user model?
UPDATE
I've tried attaching the listener in the Devise registration controller as follows:
class RegistrationsController < Devise::RegistrationsController
def create
super do |resource|
resource.subscribe(SampleDataCreator.new)
end
end
end
but it seems the listener never gets triggered.
UPDATE 2
I realised the above approach wasn't working because the record is saved before yield is called. It seems tricky to hook into Devise before this point, so instead I overrode the whole method:
def create
build_resource(sign_up_params)
resource_saved = resource.save
yield resource if block_given?
resource.subscribe(SampleDataCreator.new) # <-------------------- my addition
if resource_saved
if resource.active_for_authentication?
set_flash_message :notice, :signed_up if is_flashing_format?
sign_up(resource_name, resource)
respond_with resource, location: after_sign_up_path_for(resource)
else
set_flash_message :notice, :"signed_up_but_#{resource.inactive_message}" if is_flashing_format?
expire_data_after_sign_in!
respond_with resource, location: after_inactive_sign_up_path_for(resource)
end
else
clean_up_passwords resource
respond_with resource
end
end
This now works, although it's not very elegant.
UPDATE 3
I found a much simpler way, I can just hook into build_resource
:
class RegistrationsController < Devise::RegistrationsController
def build_resource(sign_up_params)
super.subscribe(SampleDataCreator.new)
end
end
Source: (StackOverflow)
I have a simple POST Grape endpoint with Wisper pub/sub in a background:
module Something
class Doit < Grape::API
post :now do
service = SomePub.new
service.subscribe(SomeSub.new)
service.call(params)
end
end
end
Here is the SomeSub
where actually calculations happens:
class SomeSub
def do_calculations(payload)
{result: "42"}.to_json
end
end
SomePub
is simple too:
class SomePub
include Wisper::Publisher
def call(payload)
broadcast(:do_calculations, payload)
end
end
So what I need is to respond with the JSON {result: "42"}
, when calling the Grape's post :now
endpoint.
Unfortunately it doesn't work this way, and what I have is:
{"local_registrations":[{"listener":{},"on":{},"with":null,"prefix":"","allowed_classes":[],"broadcaster":{}}]}
That example from Wisper's wiki doesn't help too much (https://github.com/krisleech/wisper/wiki/Grape)
Any ideas how to actually pass SomePub#do_calculations
results, as a result of Grape's endpoint call?
Source: (StackOverflow)
I'm trying to use Wisper with Rails 4 / AR and encountering an issue.
Let's say I have Email
and Creep
AR models, and I want the Creep
to know when a reply was received (Creep
is not necessarily the sender...)
So I do:
email = Email.create! params
creep = Creep.last
email.subscribe(creep, on: :reply_received, with: :success)
and if immediately do:
email.publish :reply_received
It will work (Creep
instances have a success method).
However, if i later do:
email = Email.find(id)
or:
email = Email.last
The event is not broadcast. I'm guessing this is because the new email is a different instance, and thus has no listeners subscribed. What am I doing wrong?
Source: (StackOverflow)
I was recommend in an earlier question to use a gem called Wisper. I am very happy to learn about it, as it is exactly the solution I'm looking for. What I can't understand from the documentation on Wisper is how listeners register themselves.
Here is my code:
app/models/subscription.rb
class Subscription < ActiveRecord::Base
include Wisper::Publisher
def some_method
# some code here
broadcast(:subscription_paused)
end
end
app/models/offer.rb
class Offer < ActiveRecord::Base
def subscription_paused
binding.pry # or whatever
end
end
So I'm not entirely sure about this part here. I've tried a variety of subscribing techniques, but I think it just comes down to me not really understanding this aspect of it:
config/initializers/wisper.rb
Wisper.subscribe(Offer.new)
I also tried, similar to the example in the Wiki:
subscription = Subscription.new
subscription.subscribe(Offer.new)
What am I missing here? (I'm not really sure if the above code should even go in an initializer.)
Source: (StackOverflow)