EzDevInfo.com

wisper

A micro library providing Ruby objects with Publish-Subscribe capabilities

reload wisper listeners automatically at every request

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)

rails wisper under test

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)

Advertisements

Not start the queue by wisper-sidekiq

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)

Using wisper (pubsub library) with Devise

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)

Wisper and Grape return results from a POST request

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)

How to use Wisper with different instances of same Active Record Model?

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)

Wisper: Subscribers not hearing broadcasts

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)