Created
February 18, 2022 22:59
-
-
Save idugalic/232bc21490f4a8976bc31e0acf548831 to your computer and use it in GitHub Desktop.
Kotlin’s context receivers - context-dependent declarations in Kotlin
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.fraktalio.application.demo | |
import com.fraktalio.fmodel.application.EventRepository | |
import com.fraktalio.fmodel.application.StateRepository | |
import com.fraktalio.fmodel.domain.Decider | |
import kotlinx.coroutines.flow.Flow | |
import kotlinx.coroutines.flow.emitAll | |
import kotlinx.coroutines.flow.flow | |
import kotlinx.coroutines.flow.fold | |
// ########################################################################## | |
// ####################### Kotlin’s context receivers ####################### | |
// ########################################################################## | |
// Context receivers enables context-dependent declarations in Kotlin. | |
// It enables composing contexts without using inheritance, which can simplify the `application` layer of the systems / orchestrates the execution of the logic. | |
// This demo is using FModel library which provides tactical Domain-Driven Design patterns, optimised for Event Sourcing, CQRS and streaming. | |
// https://github.com/fraktalio/fmodel | |
// https://fraktalio.com/blog/the-template.html | |
/** | |
* Event-sourced algorithm | |
* Computes new Events based on the previous Events and the Command. | |
*/ | |
context (Decider<C, S, E>, C) | |
private fun <C, S, E> Flow<E>.computeNewEvents(): Flow<E> = flow { | |
val currentState = fold(initialState) { s, e -> evolve(s, e) } | |
val resultingEvents = decide(this@C, currentState) | |
emitAll(resultingEvents) | |
} | |
/** | |
* State-stored algorithm | |
* Computes new State based on the previous State and the Command. | |
*/ | |
context (Decider<C, S, E>, C) | |
private suspend fun <C, S, E> S?.computeNewState(): S { | |
val currentState = this ?: initialState | |
val events = decide(this@C, currentState) | |
return events.fold(currentState) { s, e -> evolve(s, e) } | |
} | |
/** | |
* Publish command - Event-sourced decider | |
*/ | |
context (Decider<C, S, E>, EventRepository<C, E>) | |
fun <C, S, E> C.publish(): Flow<E> = fetchEvents().computeNewEvents().save() | |
/** | |
* Publish command - State-stored decider | |
*/ | |
context (Decider<C, S, E>, StateRepository<C, S>) | |
suspend fun <C, S, E> C.publish(): S = fetchState().computeNewState().save() | |
// ############################################################## | |
// ###################### build.gradle.kts ###################### | |
// ############################################################## | |
//import org.jetbrains.kotlin.gradle.tasks.KotlinCompile | |
// | |
//plugins { | |
// kotlin("jvm") version "1.6.20-M1" | |
//} | |
// | |
//tasks.withType<KotlinCompile>().configureEach { | |
// kotlinOptions { | |
// freeCompilerArgs = freeCompilerArgs + "-Xcontext-receivers" | |
// } | |
//} | |
// | |
//group = "com.fraktalio.application.demo" | |
//version = "1.0.0-SNAPSHOT" | |
// | |
//repositories { | |
// mavenCentral() | |
//} | |
// | |
//dependencies { | |
// implementation(kotlin("stdlib")) | |
// implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.0") | |
// implementation("com.fraktalio.fmodel:application:3.0.0") | |
//} | |
// ##################################################################### | |
// ########## Latest Kotlin EAP release 1.6.20-M1 is required ########## | |
// ##################################################################### | |
// - https://kotlinlang.org/docs/install-eap-plugin.html | |
// ###################################################################### | |
// ################### References and further reading ################### | |
// ###################################################################### | |
// - https://blog.jetbrains.com/kotlin/2022/02/kotlin-1-6-20-m1-released/ | |
// - https://github.com/Kotlin/KEEP/blob/master/proposals/context-receivers.md#detailed-design |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment