Add action delegate for task creation

This commit is contained in:
Alexander Nozik 2024-01-05 13:02:11 +03:00
parent 8f3c2f3950
commit 5e3de70737
5 changed files with 41 additions and 30 deletions

View File

@ -10,7 +10,6 @@ import space.kscience.dataforge.misc.ThreadSafe
import space.kscience.dataforge.names.* import space.kscience.dataforge.names.*
import kotlin.collections.set import kotlin.collections.set
import kotlin.coroutines.CoroutineContext import kotlin.coroutines.CoroutineContext
import kotlin.coroutines.coroutineContext
import kotlin.reflect.KType import kotlin.reflect.KType
import kotlin.reflect.typeOf import kotlin.reflect.typeOf
@ -21,7 +20,7 @@ public interface DataSourceBuilder<T : Any> : DataSetBuilder<T>, DataSource<T> {
/** /**
* A mutable [DataTree] that propagates updates * A mutable [DataTree] that propagates updates
*/ */
public class DataTreeBuilder<T : Any>( public class DataTreeBuilder<T : Any> internal constructor(
override val dataType: KType, override val dataType: KType,
coroutineContext: CoroutineContext, coroutineContext: CoroutineContext,
) : DataTree<T>, DataSourceBuilder<T> { ) : DataTree<T>, DataSourceBuilder<T> {
@ -100,19 +99,14 @@ public class DataTreeBuilder<T : Any>(
public fun <T : Any> DataSource( public fun <T : Any> DataSource(
type: KType, type: KType,
parent: CoroutineScope, parent: CoroutineScope,
block: DataSourceBuilder<T>.() -> Unit, block: DataSourceBuilder<T>.() -> Unit = {},
): DataTreeBuilder<T> = DataTreeBuilder<T>(type, parent.coroutineContext).apply(block) ): DataTreeBuilder<T> = DataTreeBuilder<T>(type, parent.coroutineContext).apply(block)
@Suppress("OPT_IN_USAGE", "FunctionName") @Suppress("OPT_IN_USAGE", "FunctionName")
public inline fun <reified T : Any> DataSource( public inline fun <reified T : Any> DataSource(
parent: CoroutineScope, parent: CoroutineScope,
crossinline block: DataSourceBuilder<T>.() -> Unit,
): DataTreeBuilder<T> = DataSource(typeOf<T>(), parent) { block() }
@Suppress("FunctionName")
public suspend inline fun <reified T : Any> DataSource(
crossinline block: DataSourceBuilder<T>.() -> Unit = {}, crossinline block: DataSourceBuilder<T>.() -> Unit = {},
): DataTreeBuilder<T> = DataTreeBuilder<T>(typeOf<T>(), coroutineContext).apply { block() } ): DataTreeBuilder<T> = DataSource(typeOf<T>(), parent) { block() }
public inline fun <reified T : Any> DataSourceBuilder<T>.emit( public inline fun <reified T : Any> DataSourceBuilder<T>.emit(
name: Name, name: Name,

View File

@ -65,13 +65,11 @@ internal class StaticDataTree<T : Any>(
} }
} }
@Suppress("FunctionName")
public inline fun <T : Any> DataTree( public inline fun <T : Any> DataTree(
dataType: KType, dataType: KType,
block: DataSetBuilder<T>.() -> Unit, block: DataSetBuilder<T>.() -> Unit,
): DataTree<T> = StaticDataTree<T>(dataType).apply { block() } ): DataTree<T> = StaticDataTree<T>(dataType).apply { block() }
@Suppress("FunctionName")
public inline fun <reified T : Any> DataTree( public inline fun <reified T : Any> DataTree(
noinline block: DataSetBuilder<T>.() -> Unit, noinline block: DataSetBuilder<T>.() -> Unit,
): DataTree<T> = DataTree(typeOf<T>(), block) ): DataTree<T> = DataTree(typeOf<T>(), block)

View File

@ -29,7 +29,7 @@ internal class ActionsTest {
@Test @Test
fun testDynamicMapAction() = runTest { fun testDynamicMapAction() = runTest {
val data: DataSourceBuilder<Int> = DataSource() val data: DataSourceBuilder<Int> = DataSource(this)
val plusOne = Action.mapping<Int, Int> { val plusOne = Action.mapping<Int, Int> {
result { it + 1 } result { it + 1 }

View File

@ -56,7 +56,7 @@ internal class DataTreeBuilderTest {
try { try {
lateinit var updateJob: Job lateinit var updateJob: Job
supervisorScope { supervisorScope {
val subNode = DataSource<Int> { val subNode = DataSource<Int>(this) {
updateJob = launch { updateJob = launch {
repeat(10) { repeat(10) {
delay(10) delay(10)
@ -70,7 +70,7 @@ internal class DataTreeBuilderTest {
println(it) println(it)
} }
} }
val rootNode = DataSource<Int> { val rootNode = DataSource<Int>(this) {
setAndWatch("sub".asName(), subNode) setAndWatch("sub".asName(), subNode)
} }

View File

@ -1,18 +1,17 @@
package space.kscience.dataforge.workspace package space.kscience.dataforge.workspace
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import space.kscience.dataforge.actions.Action
import space.kscience.dataforge.context.Context import space.kscience.dataforge.context.Context
import space.kscience.dataforge.context.ContextBuilder import space.kscience.dataforge.context.ContextBuilder
import space.kscience.dataforge.context.Global import space.kscience.dataforge.context.Global
import space.kscience.dataforge.data.* import space.kscience.dataforge.data.DataSet
import space.kscience.dataforge.meta.Meta import space.kscience.dataforge.data.DataSource
import space.kscience.dataforge.meta.MetaRepr import space.kscience.dataforge.data.DataSourceBuilder
import space.kscience.dataforge.meta.MetaSpec import space.kscience.dataforge.meta.*
import space.kscience.dataforge.meta.MutableMeta
import space.kscience.dataforge.meta.descriptors.MetaDescriptor import space.kscience.dataforge.meta.descriptors.MetaDescriptor
import space.kscience.dataforge.meta.descriptors.MetaDescriptorBuilder import space.kscience.dataforge.meta.descriptors.MetaDescriptorBuilder
import space.kscience.dataforge.misc.DFBuilder import space.kscience.dataforge.misc.DFBuilder
import space.kscience.dataforge.misc.DFExperimental
import space.kscience.dataforge.names.Name import space.kscience.dataforge.names.Name
import space.kscience.dataforge.names.asName import space.kscience.dataforge.names.asName
import kotlin.collections.set import kotlin.collections.set
@ -45,6 +44,9 @@ public inline fun <reified T : Any> TaskContainer.registerTask(
noinline builder: suspend TaskResultBuilder<T>.() -> Unit, noinline builder: suspend TaskResultBuilder<T>.() -> Unit,
): Unit = registerTask(Name.parse(name), Task(MetaDescriptor(descriptorBuilder), builder)) ): Unit = registerTask(Name.parse(name), Task(MetaDescriptor(descriptorBuilder), builder))
/**
* Create a new t
*/
public inline fun <reified T : Any> TaskContainer.buildTask( public inline fun <reified T : Any> TaskContainer.buildTask(
name: String, name: String,
descriptorBuilder: MetaDescriptorBuilder.() -> Unit = {}, descriptorBuilder: MetaDescriptorBuilder.() -> Unit = {},
@ -67,6 +69,9 @@ public inline fun <reified T : Any> TaskContainer.task(
ReadOnlyProperty { _, _ -> TaskReference(taskName, task) } ReadOnlyProperty { _, _ -> TaskReference(taskName, task) }
} }
/**
* Create a task based on [MetaSpec]
*/
public inline fun <reified T : Any, C : MetaRepr> TaskContainer.task( public inline fun <reified T : Any, C : MetaRepr> TaskContainer.task(
specification: MetaSpec<C>, specification: MetaSpec<C>,
noinline builder: suspend TaskResultBuilder<T>.(C) -> Unit, noinline builder: suspend TaskResultBuilder<T>.(C) -> Unit,
@ -77,15 +82,34 @@ public inline fun <reified T : Any, C : MetaRepr> TaskContainer.task(
ReadOnlyProperty { _, _ -> TaskReference(taskName, task) } ReadOnlyProperty { _, _ -> TaskReference(taskName, task) }
} }
/**
* A delegate to create a custom task
*/
public inline fun <reified T : Any> TaskContainer.task( public inline fun <reified T : Any> TaskContainer.task(
noinline descriptorBuilder: MetaDescriptorBuilder.() -> Unit = {}, noinline descriptorBuilder: MetaDescriptorBuilder.() -> Unit = {},
noinline builder: suspend TaskResultBuilder<T>.() -> Unit, noinline builder: suspend TaskResultBuilder<T>.() -> Unit,
): PropertyDelegateProvider<Any?, ReadOnlyProperty<Any?, TaskReference<T>>> = ): PropertyDelegateProvider<Any?, ReadOnlyProperty<Any?, TaskReference<T>>> =
task(MetaDescriptor(descriptorBuilder), builder) task(MetaDescriptor(descriptorBuilder), builder)
public class WorkspaceBuilder(private val parentContext: Context = Global) : TaskContainer { /**
* A delegate for creating a task based on [action]
*/
public inline fun <T : Any, reified R : Any> TaskContainer.action(
selector: DataSelector<T>,
action: Action<T, R>,
noinline metaTransform: MutableMeta.()-> Unit = {},
noinline descriptorBuilder: MetaDescriptorBuilder.() -> Unit = {},
): PropertyDelegateProvider<Any?, ReadOnlyProperty<Any?, TaskReference<R>>> =
task(MetaDescriptor(descriptorBuilder)) {
result(action.execute(from(selector), taskMeta.copy(metaTransform)))
}
public class WorkspaceBuilder(
private val parentContext: Context = Global,
private val coroutineScope: CoroutineScope = parentContext,
) : TaskContainer {
private var context: Context? = null private var context: Context? = null
private var data: DataSet<*>? = null private val data = DataSource<Any>(coroutineScope)
private val targets: HashMap<String, Meta> = HashMap() private val targets: HashMap<String, Meta> = HashMap()
private val tasks = HashMap<Name, Task<*>>() private val tasks = HashMap<Name, Task<*>>()
private var cache: WorkspaceCache? = null private var cache: WorkspaceCache? = null
@ -100,13 +124,8 @@ public class WorkspaceBuilder(private val parentContext: Context = Global) : Tas
/** /**
* Define intrinsic data for the workspace * Define intrinsic data for the workspace
*/ */
public fun data(builder: DataSetBuilder<Any>.() -> Unit) { public fun data(builder: DataSourceBuilder<Any>.() -> Unit) {
data = DataTree(builder) data.apply(builder)
}
@DFExperimental
public fun data(scope: CoroutineScope, builder: DataSourceBuilder<Any>.() -> Unit) {
data = DataSource(scope, builder)
} }
/** /**
@ -132,7 +151,7 @@ public class WorkspaceBuilder(private val parentContext: Context = Global) : Tas
val postProcess: suspend (TaskResult<*>) -> TaskResult<*> = { result -> val postProcess: suspend (TaskResult<*>) -> TaskResult<*> = { result ->
cache?.evaluate(result) ?: result cache?.evaluate(result) ?: result
} }
return WorkspaceImpl(context ?: parentContext, data ?: DataSet.EMPTY, targets, tasks, postProcess) return WorkspaceImpl(context ?: parentContext, data, targets, tasks, postProcess)
} }
} }