GithubHelp home page GithubHelp logo

Comments (6)

rromanchuk avatar rromanchuk commented on August 22, 2024 2

BTW Using StripeEvent.configure do |events| in a config/initializers/stripe.rb (as shown in the README) and assigning classes that live in /app is going to cause problems in rails6+

from stripe_event.

christianrolle avatar christianrolle commented on August 22, 2024 2

@kirylpl related to the subscribed class, like:

StripeEvent.configure do |events|
  events.subscribe 'charge.failed', Stripe::ChargeFailedInteractor
end

and

module Stripe
  class FailedChargeInteractor
    include Interactor
    
    def call(event)
      Rails.logger.error("Stripe charge failed: #{params}")
    end
  end
end

and then running the server with rails s:

uninitialized constant Stripe::ChargeFailedInteractor (NameError)

from stripe_event.

rmm5t avatar rmm5t commented on August 22, 2024

A documentation PR is welcome, though it should probably be more specific about the fact that event subscriptions are singletons that just respond to call.

With that said, and/or alternatively, and/or optimally, I suppose there's also room to adjust the StripeEvent::NotificationAdapter#call to instantiate a new instance if the passed subscriber is a Class as opposed to an instance of something that responds to #call itself. I'd be willing to review a PR (with specs) that does that.

from stripe_event.

yannis avatar yannis commented on August 22, 2024

First, I'd like to thank you for the great gem which helped us a lot while integrating Stripe in our app.

Still, we were victim of the memoization issue, and I'd like to insist on the fact that the use of a Singleton, instantiated in an initializer can lead to a lot of issues.
Indeed, any setting of an instance variable in the recorder is a mistake since it can change anytime, even in the middle of a method call.
For example, we had something like this (code simplified for clarity):

class StripeInvoiceRecorder
  attr_reader :action, event

  def initialize(action:)
    @action = action
  end

  def call(event)
    @event = event
     send(action)
  end

  private def payment_succeeded
    object = event["data"]["object"]
    SubscriptionJob1.perform_later(subscription_stripe_id: object["subscription"])
    SubscriptionJob2.perform_later(stripe_invoice_id: object["id"])
  end
end

Here, instantiating @event = event in #call is a mistake as any other call to #call during the execution of #payment_succeeded will change the value of @event changing object mid-flight.

So to prevent this issue, we changed this code to:

class StripeInvoiceRecorder
  attr_reader :action

  def initialize(action:)
    @action = action
  end

  def call(event)
     send(action, event)
  end

  private def payment_succeeded(event)
    object = event["data"]["object"]
    SubscriptionJob1.perform_later(subscription_stripe_id: object["subscription"])
    SubscriptionJob2.perform_later(stripe_invoice_id: object["id"])
  end
end

I hope it will help other having strange issues with their recorders.
And indeed, switching from a Singleton to instance variables would prevent this kind of issues.

from stripe_event.

vakrolme avatar vakrolme commented on August 22, 2024

+1, and I would expand this to code reloading also, since I've just spent some hours figuring out why code reloading doesn't work with a service object that I pass into the above mentioned initializer (thought it to be a Zeitwerk issue or something).

In hindsight it all makes sense. But it isn't obvious if you just mindlessly follow the setup guide.

from stripe_event.

kirylrb avatar kirylrb commented on August 22, 2024

@rromanchuk What kind of problems you mean?

from stripe_event.

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.