Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Message-driven application made easy with Water...

Message-driven application made easy with Watermill – Robert Laszczak

GopherCon Russia

April 13, 2019
Tweet

More Decks by GopherCon Russia

Other Decks in Programming

Transcript

  1. roblaszczak r.Post("/book-room", func(w http.ResponseWriter, r *http.Request) { // ... if

    err := bookingRepo.AddBooking(booking); err != nil { panic(err) } err := paymentsInitializer.InitializePayment(p) if err != nil { panic(err) } })
  2. roblaszczak err := bookingRepo.AddBooking(booking) //... event, err := json.Marshal(RoomBooked{ BookingUUID:

    booking.ID(), RoomID: req.RoomID, Price: booking.Price(), PaymentChannel: req.PaymentChannel, }) //... err := publisher.Publish( "room_bookings", message.NewMessage(watermill.NewUUID(), event), ) //...
  3. roblaszczak watermillRouter, err := message.NewRouter( message.RouterConfig{}, watermillLogger, ) if err

    != nil { panic(err) } watermillRouter.AddMiddleware(watermillMiddleware.Recoverer)
  4. roblaszczak watermillRouter.AddNoPublisherHandler( "book_room_handler", // handler name "room_bookings", //subscribe topic subscriber,

    func(msg *message.Message) ([]*message.Message, error) { event := RoomBooked{} err := json.Unmarshal(msg.Payload, &event) // ... p, err := payment.NewPayment(event.Price, event.Channel) // ... err := paymentsInitializer.InitializePayment(p) // ... return nil, nil }, )
  5. roblaszczak pq, err := watermillMiddleware.NewPoisonQueue( publisher, "poison_queue" ) // ...

    watermillRouter.AddMiddleware( pq.Middleware, watermillMiddleware.Retry{ MaxRetries: 1, Logger: watermillLogger, }.Middleware, )
  6. roblaszczak pq, err := watermillMiddleware.NewPoisonQueueWithFilter( publisher, "poison_queue", func(err error) bool

    { switch errors.Cause(err).(type) { case *json.InvalidUnmarshalError: return true Default: return false } }, )
  7. roblaszczak func (BookingsCounterGenerator) NewEvent() interface{} { return &event.RoomBooked{} } func

    (b BookingsCounterGenerator) Handle(e interface{}) error { event := e.(*event.RoomBooked) return b.i.IncrementBookingCounter(event.BookingUUID) }
  8. roblaszczak METRICS prometheusRegistry, closeMetricsServer := metrics.CreateRegistryAndServeHTTP(":8081") defer closeMetricsServer() metricsBuilder :=

    metrics.NewPrometheusMetricsBuilder(prometheusRegistry, "", "") metricsBuilder.AddPrometheusRouterMetrics(watermillRouter)
  9. roblaszczak 23:09:35 [INFO] Booking 01D6P9VAFXEGXHAF6MW4ZRZD8V done 23:09:37 [INFO] Booking 01D6P9STY5CCN8RJT4YNTHFZRH

    done 23:09:37 [ERROR] Lost Kafka connection 23:09:38 [INFO] Connecting to Kafka 23:09:41 [INFO] Booking 01D6P9STY5CCN8RJT4YNTHFZRH done 23:09:35 [INFO] Booking 01D6P9VTE0QNCESP805MVH9Z1K done
  10. roblaszczak 23:09:35 [INFO] Booking 01D6P9VAFXEGXHAF6MW4ZRZD8V done 23:09:37 [INFO] Booking 01D6P9STY5CCN8RJT4YNTHFZRH

    done 23:09:37 [ERROR] Lost Kafka connection 23:09:38 [INFO] Connecting to Kafka 23:09:41 [INFO] Booking 01D6P9STY5CCN8RJT4YNTHFZRH done 23:09:35 [INFO] Booking 01D6P9VTE0QNCESP805MVH9Z1K done
  11. roblaszczak func (m *MemoryBookings) IncrementBookingCounter(bookingUUID string) error { m.lock.Lock() defer

    m.lock.Unlock() if m.bookings == nil { m.bookings = map[string]struct{}{} } if _, ok := m.bookings[bookingUUID]; ok { // deduplicated return nil } m.bookings[bookingUUID] = struct{}{} m.count += 1 return nil }