Skip to content

Commit

Permalink
changes middleware api to include an initialization phase
Browse files Browse the repository at this point in the history
* middlware that wants to support long running processes - across multiple actions - can be written easier this way

NOTE

* introduces an issue that has been already discussed here: reduxjs/redux#1240
  • Loading branch information
encodeering committed Mar 25, 2017
1 parent e9fed56 commit 288e112
Show file tree
Hide file tree
Showing 6 changed files with 37 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package com.encodeering.conflate.api

interface Middleware<in State> {

suspend fun dispatch (action : Action, connection : Connection<State>)
fun interceptor (connection : Connection<State>) : Interceptor

interface Connection<out State> {

Expand All @@ -14,4 +14,10 @@ interface Middleware<in State> {

}

interface Interceptor {

suspend fun dispatch (action : Action)

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,10 @@ class Logging<in State> (
val exception : () -> Boolean = { true }
) : Middleware<State> {

suspend override fun dispatch (action : Action, connection : Middleware.Connection<State>) {
override fun interceptor (connection : Middleware.Connection<State>) : Middleware.Interceptor {
return object : Middleware.Interceptor {

suspend override fun dispatch (action : Action) {
if (before ()) debug (">>", action)

try {
Expand All @@ -27,10 +30,13 @@ class Logging<in State> (

throw e
}
}
}

private fun debug (prefix : CharSequence, action : Action) = log ("$prefix {}", action)

}
}

companion object {

private val logger : Logger by lazy { LoggerFactory.getLogger (Logging::class.java) }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ class LoggingTest : Spek({
val logging = logging (before = true, log = log)

co {
logging.dispatch (action, connection ())
logging.interceptor (connection ()).dispatch (action)

verify (log).invoke (">> {}", action)
verifyNoMoreInteractions (log)
Expand All @@ -54,7 +54,7 @@ class LoggingTest : Spek({
val logging = logging (after = true, log = log)

co {
logging.dispatch (action, connection ())
logging.interceptor (connection ()).dispatch (action)

verify (log).invoke ("-- {}", action)
verifyNoMoreInteractions (log)
Expand All @@ -70,7 +70,7 @@ class LoggingTest : Spek({
throws<IllegalStateException> {
co {
try {
logging.dispatch (action, connection (next = { throw IllegalStateException () }))
logging.interceptor (connection (next = { throw IllegalStateException () })).dispatch (action)
} finally {
verify (log).invoke ("!! {}", action)
verifyNoMoreInteractions (log)
Expand All @@ -86,7 +86,7 @@ class LoggingTest : Spek({
val logging = logging (exception = true, log = log ())

co {
logging.dispatch (action, connection (next = next))
logging.interceptor (connection (next = next)).dispatch (action)

verify (next).invoke (action)
}
Expand All @@ -100,7 +100,7 @@ class LoggingTest : Spek({
val logging = logging (before = true, after = true, log = log)

co {
logging.dispatch (action, connection (next = next))
logging.interceptor (connection (next = next)).dispatch (action)

val ordered = Mockito.inOrder (log, next)
ordered.verify (log).invoke (eq (">> {}"), eq (action))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,16 @@ object Middlewares {
after : (Action, Middleware.Connection<T>) -> Unit = { _, _ -> Unit }) =
object : Middleware<T> {

suspend override fun dispatch (action : Action, connection : Middleware.Connection<T>) {
override fun interceptor(connection : Middleware.Connection<T>) : Middleware.Interceptor {
return object : Middleware.Interceptor {

suspend override fun dispatch (action : Action) {
before (action, connection)
connection.next (action)
after (action, connection)
}

}
}

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ class Conflate<out State> (

private class Next<out State> (private var resolve : () -> State, private val dispatch : suspend (Action) -> Unit, private val middleware : Middleware<State>, private val next : Middleware.Connection<State>) : Middleware.Connection<State> {

val interceptor = middleware.interceptor (next)

override val state : State
get () = resolve ()

Expand All @@ -80,7 +82,7 @@ class Conflate<out State> (
}

suspend override fun next (action : Action) {
middleware.dispatch (action, next)
interceptor.dispatch (action)
}

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,16 @@ import com.encodeering.conflate.api.Middleware

internal class Codeblock<in State> (private val block : (Action, State) -> Unit) : Middleware<State> {

suspend override fun dispatch (action : Action, connection : Middleware.Connection<State>) {
override fun interceptor(connection : Middleware.Connection<State>) : Middleware.Interceptor {
return object : Middleware.Interceptor {

suspend override fun dispatch (action : Action) {
connection.apply {
block (action, connection.state)
next (action)
}
}

}
}

Expand Down

0 comments on commit 288e112

Please sign in to comment.