Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add transient state #32

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 7 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
[![CI](https://github.com/day8/re-frame-async-flow-fx/workflows/ci/badge.svg)](https://github.com/day8/re-frame-async-flow-fx/actions?workflow=ci)
[![CD](https://github.com/day8/re-frame-async-flow-fx/workflows/cd/badge.svg)](https://github.com/day8/re-frame-async-flow-fx/actions?workflow=cd)
[![GitHub tag (latest by date)](https://img.shields.io/github/v/tag/day8/re-frame-async-flow-fx?style=flat)](https://github.com/day8/re-frame-async-flow-fx/tags)
[![GitHub tag (latest by date)](https://img.shields.io/github/v/tag/lumanu/re-frame-async-flow-fx?style=flat)](https://github.com/lumanu/re-frame-async-flow-fx/tags)
[![Clojars Project](https://img.shields.io/clojars/v/day8.re-frame/async-flow-fx.svg)](https://clojars.org/day8.re-frame/async-flow-fx)
[![GitHub issues](https://img.shields.io/github/issues-raw/day8/re-frame-async-flow-fx?style=flat)](https://github.com/day8/re-frame-async-flow-fx/issues)
[![GitHub pull requests](https://img.shields.io/github/issues-pr/day8/re-frame-async-flow-fx)](https://github.com/day8/re-frame-async-flow-fx/pulls)
[![License](https://img.shields.io/github/license/day8/re-frame-async-flow-fx.svg)](LICENSE)

## Async Control Flow In re-frame
Expand Down Expand Up @@ -381,6 +377,7 @@ A `rule` is a map with the following fields:
- `:dispatch-n` to dispatch multiple events, must be a coll where each elem represents one event to dispatch.
- `:dispatch-fn` can be a function that accepts the seen event, and returns a coll where each elem represents one event to dispatch.
- `:halt?` optional boolean. If true, the flow enters teardown and stops.
- `:transient?` optional boolean. If true, the flow will allow the rule to be executed multiple times.


### Under The Covers
Expand Down Expand Up @@ -426,7 +423,11 @@ Or, to dispatch a server error event if a status of 500 or above has been seen
```clj
{:when :seen? :events (fn [[e status]] (and (= e :http/response-received) (>= status 500)))
:dispatch [:server/error]))
```
```

Furthermore, sometimes it might be helpful to allow rules to be executed more than once. For these cases set
`:transient?` to `true`. This way the system will not track that the rule has fired and will allow it to execute
any number of times.


## Design Philosophy
Expand Down
4 changes: 2 additions & 2 deletions project.clj
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
(defproject day8.re-frame/async-flow-fx "lein-git-inject/version"
(defproject lumanu/async-flow-fx "lein-git-inject/version"
:description "A re-frame effects handler for coordinating the kind of async control flow which often happens on app startup."
:url "https://github.com/day8/re-frame-async-flow-fx.git"
:url "https://github.com/lumanu/re-frame-async-flow-fx.git"
:license {:name "MIT"}

:min-lein-version "2.9.0"
Expand Down
5 changes: 3 additions & 2 deletions src/day8/re_frame/async_flow_fx.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -63,12 +63,13 @@
- add a unique :id, if one not already present"
[rules]
(->> rules
(map-indexed (fn [index {:as rule :keys [id when events dispatch dispatch-n dispatch-fn halt?]}]
(map-indexed (fn [index {:as rule :keys [id when events transient? dispatch dispatch-n dispatch-fn halt?]}]
(if (< 1 (count (remove nil? [dispatch dispatch-n dispatch-fn])))
(re-frame/console :error
"async-flow: rule can only specify one of :dispatch, :dispatch-n and :dispatch-fn. Got more than one: " rule)
(cond-> {:id (or id index)
:halt? (or halt? false)
:transient? (or transient? false)
:when (when->fn when)
:events (if (coll? events) (set events) (hash-set events))}
dispatch-fn (assoc :dispatch-fn dispatch-fn)
Expand Down Expand Up @@ -149,7 +150,7 @@
new-seen-events (conj seen-events forwarded-event)
ready-rules (startable-rules rules new-seen-events rules-fired)
halt? (some :halt? ready-rules)
ready-rules-ids (->> ready-rules (map :id) set)
ready-rules-ids (->> ready-rules (filter #(not (:transient? %))) (map :id) set)
new-rules-fired (set/union rules-fired ready-rules-ids)
new-dispatches (rules->dispatches ready-rules forwarded-event)
new-db (set-state db new-seen-events new-rules-fired)]
Expand Down
23 changes: 20 additions & 3 deletions test/day8/re_frame/async_flow_fx_test.cljs
Original file line number Diff line number Diff line change
Expand Up @@ -58,13 +58,13 @@

(deftest test-massage-rules
(is (= (core/massage-rules [{:when :seen? :events :1 :dispatch [:2]}])
(list {:id 0 :when core/seen-all-of? :events #{:1} :halt? false :dispatch-n (list [:2])})))
(list {:id 0 :when core/seen-all-of? :events #{:1} :transient? false :halt? false :dispatch-n (list [:2])})))

(is (= (core/massage-rules [{:when :seen-both? :events [:1 :2] :halt? true}])
(list {:id 0 :when core/seen-all-of? :events #{:1 :2} :halt? true :dispatch-n '()})))
(list {:id 0 :when core/seen-all-of? :events #{:1 :2} :transient? false :halt? true :dispatch-n '()})))

(is (= (core/massage-rules [{:when :seen-any-of? :events #{:1 :2} :dispatch [:2] :halt? true}])
(list {:id 0 :when core/seen-any-of? :events #{:1 :2} :halt? true :dispatch-n (list [:2])}))))
(list {:id 0 :when core/seen-any-of? :events #{:1 :2} :transient? false :halt? true :dispatch-n (list [:2])}))))


(deftest test-setup
Expand Down Expand Up @@ -185,6 +185,23 @@
{:db {:p {:seen-events #{[:4 :b]} :rules-fired #{2}}}
:dispatch-n [[:6]]}))))

(deftest test-transient-handling
(let [flow {:first-dispatch [:start]
:id :test-id
:db-path [:p]
:rules [{:id 0 :when :seen? :transient? true :events [[:1 :a]] :dispatch [:2]}
{:id 2 :when :seen-any-of? :events [[:4 :b] :5] :dispatch [:6]}
]}
handler-fn (core/make-flow-event-handler flow)]

;; new event should cause a dispatch and not track rules-fired
(is (= (handler-fn
{:db {:p {:seen-events #{}
:rules-fired #{}}}}
[:test-id [:1 :a]])
{:db {:p {:seen-events #{[:1 :a]} :rules-fired #{}}}
:dispatch-n [[:2]]}))))

(deftest test-halt1
(let [flow {:first-dispatch [:start]
:id :test-id
Expand Down