You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

73 lines
1.8 KiB

  1. package nova.monadic_sfx.util.reactive
  2. import cats.effect.Sync
  3. import monix.bio.Task
  4. import monix.execution.Scheduler
  5. import monix.reactive.Observable
  6. import monix.reactive.OverflowStrategy
  7. import monix.reactive.subjects.ConcurrentSubject
  8. object Store {
  9. def createL[A, M](
  10. initialAction: A,
  11. initialState: M,
  12. reducer: Reducer[A, M],
  13. middlewares: Seq[Middleware[A, M]] = Seq.empty,
  14. overflowStrategy: OverflowStrategy.Synchronous[A] =
  15. OverflowStrategy.DropOld(50)
  16. ) =
  17. Task.deferAction { implicit s =>
  18. Task {
  19. val subject = ConcurrentSubject.publish[A](overflowStrategy)
  20. val fold: ((A, M), A) => (A, M) = {
  21. case ((_, state), action) => {
  22. val (newState, effects) = reducer(state, action)
  23. effects.subscribe(subject.onNext _)
  24. action -> newState
  25. }
  26. }
  27. val obs = subject
  28. .scan[(A, M)](initialAction -> initialState)(fold)
  29. .behavior(initialAction -> initialState)
  30. .refCount
  31. val res = middlewares.view.reverse.foldLeft(obs) {
  32. case (obs, middleware) => middleware(obs)
  33. }
  34. MonixProSubject.from(
  35. subject,
  36. res
  37. )
  38. }
  39. }
  40. def create[F[_], A, M](
  41. initialAction: A,
  42. initialState: M,
  43. reducer: Reducer[A, M]
  44. )(implicit s: Scheduler, F: Sync[F]): F[Observable[(A, M)]] =
  45. F.delay {
  46. val subject = ConcurrentSubject.publish[A]
  47. val fold: ((A, M), A) => (A, M) = {
  48. case ((_, state), action) => {
  49. val (newState, effects) = reducer(state, action)
  50. effects.subscribe(subject.onNext _)
  51. action -> newState
  52. }
  53. }
  54. subject
  55. .scan[(A, M)](initialAction -> initialState)(fold)
  56. .behavior(initialAction -> initialState)
  57. .refCount
  58. }
  59. }