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.

97 lines
2.5 KiB

  1. package nova.monadic_sfx.util.reactive
  2. import io.circe.Encoder
  3. import io.odin.Logger
  4. import monix.bio.Task
  5. import monix.reactive.OverflowStrategy
  6. import monix.reactive.subjects.ConcurrentSubject
  7. object Store {
  8. def createL[A, M](
  9. initialAction: A,
  10. initialState: M,
  11. reducer: Reducer[A, M],
  12. middlewares: Seq[Middleware[A, M]] = Seq.empty,
  13. overflowStrategy: OverflowStrategy.Synchronous[A] =
  14. OverflowStrategy.DropOld(50)
  15. ): Task[Store[A, M]] =
  16. Task.deferAction { implicit s =>
  17. Task {
  18. val subject = ConcurrentSubject.publish[A](overflowStrategy)
  19. val fold: ((A, M), A) => (A, M) = {
  20. case ((_, state), action) => {
  21. val (newState, effects) = reducer(state, action)
  22. effects.subscribe(subject.onNext _)
  23. action -> newState
  24. }
  25. }
  26. val obs = subject
  27. .scan[(A, M)](initialAction -> initialState)(fold)
  28. .behavior(initialAction -> initialState)
  29. .refCount
  30. val res = middlewares.foldLeft(obs) {
  31. case (obs, middleware) => middleware(obs)
  32. }
  33. MonixProSubject.from(
  34. subject,
  35. res
  36. )
  37. }
  38. }
  39. def createJsonL[A: Encoder, M](
  40. initialAction: A,
  41. initialState: M,
  42. reducer: Reducer[A, M],
  43. storeName: String,
  44. logger: Logger[Task],
  45. middlewares: Seq[Middleware[A, M]] = Seq.empty,
  46. overflowStrategy: OverflowStrategy.Synchronous[A] =
  47. OverflowStrategy.DropOld(50)
  48. ): Task[Store[A, M]] =
  49. Task.deferAction { implicit s =>
  50. Task {
  51. val subject = ConcurrentSubject.publish[A](overflowStrategy)
  52. val fold: ((A, M), A) => Task[(A, M)] = {
  53. case ((_, state), action) =>
  54. Task {
  55. val (newState, effects) = reducer(state, action)
  56. effects.subscribe(subject.onNext _)
  57. action -> newState
  58. }
  59. }
  60. val obs = subject
  61. .doOnNextF(action =>
  62. logger.debug(
  63. StoreInfo(storeName, action)
  64. ) // .executeOn(Scheduler.global)
  65. )
  66. // .doOnNextF(action => Coeval(println(action)))
  67. .scanEvalF[Task, (A, M)](Task.pure(initialAction -> initialState))(
  68. fold
  69. )
  70. .behavior(initialAction -> initialState)
  71. .refCount
  72. // val res = middlewares.foldLeft(obs) {
  73. // case (obs, middleware) => middleware(obs)
  74. // }
  75. MonixProSubject.from(
  76. subject,
  77. obs
  78. )
  79. }
  80. }
  81. }