Add preemptive initialization for plugins
This commit is contained in:
parent
d5992c721d
commit
3ab3f2766c
@ -39,12 +39,11 @@ public final class hep/dataforge/context/ClassLoaderPluginKt {
|
||||
public class hep/dataforge/context/Context : hep/dataforge/context/Named, hep/dataforge/meta/MetaRepr, hep/dataforge/provider/Provider, kotlinx/coroutines/CoroutineScope {
|
||||
public static final field Companion Lhep/dataforge/context/Context$Companion;
|
||||
public static final field PROPERTY_TARGET Ljava/lang/String;
|
||||
public fun <init> (Lhep/dataforge/names/Name;Lhep/dataforge/context/Context;Lhep/dataforge/meta/Meta;)V
|
||||
public final fun activate (Ljava/lang/Object;)V
|
||||
public fun <init> (Lhep/dataforge/names/Name;Lhep/dataforge/context/Context;Lhep/dataforge/meta/Meta;Ljava/util/Set;)V
|
||||
public synthetic fun <init> (Lhep/dataforge/names/Name;Lhep/dataforge/context/Context;Lhep/dataforge/meta/Meta;Ljava/util/Set;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
public fun close ()V
|
||||
public fun content (Ljava/lang/String;)Ljava/util/Map;
|
||||
public final fun content (Ljava/lang/String;Z)Ljava/util/Map;
|
||||
public final fun deactivate (Ljava/lang/Object;)V
|
||||
public fun getCoroutineContext ()Lkotlin/coroutines/CoroutineContext;
|
||||
public fun getDefaultChainTarget ()Ljava/lang/String;
|
||||
public fun getDefaultTarget ()Ljava/lang/String;
|
||||
@ -52,7 +51,6 @@ public class hep/dataforge/context/Context : hep/dataforge/context/Named, hep/da
|
||||
public final fun getName ()Lhep/dataforge/names/Name;
|
||||
public final fun getParent ()Lhep/dataforge/context/Context;
|
||||
public final fun getPlugins ()Lhep/dataforge/context/PluginManager;
|
||||
public final fun isActive ()Z
|
||||
public fun toMeta ()Lhep/dataforge/meta/Meta;
|
||||
}
|
||||
|
||||
@ -152,7 +150,7 @@ public final class hep/dataforge/context/PluginFactory$Companion {
|
||||
}
|
||||
|
||||
public final class hep/dataforge/context/PluginManager : hep/dataforge/context/ContextAware, java/lang/Iterable, kotlin/jvm/internal/markers/KMappedMarker {
|
||||
public fun <init> (Lhep/dataforge/context/Context;)V
|
||||
public fun <init> (Lhep/dataforge/context/Context;Ljava/util/Set;)V
|
||||
public final fun fetch (Lhep/dataforge/context/PluginFactory;ZLhep/dataforge/meta/Meta;)Lhep/dataforge/context/Plugin;
|
||||
public final fun fetch (Lhep/dataforge/context/PluginFactory;ZLkotlin/jvm/functions/Function1;)Lhep/dataforge/context/Plugin;
|
||||
public static synthetic fun fetch$default (Lhep/dataforge/context/PluginManager;Lhep/dataforge/context/PluginFactory;ZLhep/dataforge/meta/Meta;ILjava/lang/Object;)Lhep/dataforge/context/Plugin;
|
||||
|
@ -28,6 +28,7 @@ public open class Context(
|
||||
final override val name: Name,
|
||||
public val parent: Context?,
|
||||
meta: Meta,
|
||||
plugins: Set<Plugin> = emptySet(),
|
||||
) : Named, MetaRepr, Provider, CoroutineScope {
|
||||
|
||||
/**
|
||||
@ -47,32 +48,7 @@ public open class Context(
|
||||
/**
|
||||
* A [PluginManager] for current context
|
||||
*/
|
||||
public val plugins: PluginManager = PluginManager(this)
|
||||
|
||||
@Deprecated("To be removed in favor of immutable plugins")
|
||||
private val activators = HashSet<Any>()
|
||||
|
||||
/**
|
||||
* Defines if context is used in any kind of active computations. Active context properties and plugins could not be changed
|
||||
*/
|
||||
@Deprecated("To be removed in favor of immutable plugins")
|
||||
public val isActive: Boolean = activators.isNotEmpty()
|
||||
|
||||
/**
|
||||
* Mark context as active and used by [activator]
|
||||
*/
|
||||
@Deprecated("To be removed in favor of immutable plugins")
|
||||
public fun activate(activator: Any) {
|
||||
activators.add(activator)
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark context unused by [activator]
|
||||
*/
|
||||
@Deprecated("To be removed in favor of immutable plugins")
|
||||
public fun deactivate(activator: Any) {
|
||||
activators.remove(activator)
|
||||
}
|
||||
public val plugins: PluginManager by lazy { PluginManager(this, plugins)}
|
||||
|
||||
override val defaultTarget: String get() = Plugin.TARGET
|
||||
|
||||
@ -104,8 +80,6 @@ public open class Context(
|
||||
* Detach all plugins and terminate context
|
||||
*/
|
||||
public open fun close() {
|
||||
@Suppress("DEPRECATION")
|
||||
if (isActive) error("Can't close active context")
|
||||
//detach all plugins
|
||||
plugins.forEach { it.detach() }
|
||||
}
|
||||
|
@ -8,7 +8,7 @@ import hep.dataforge.names.toName
|
||||
*/
|
||||
@DFBuilder
|
||||
public class ContextBuilder(private val parent: Context = Global, public var name: String = "@anonymous") {
|
||||
private val plugins = ArrayList<Plugin>()
|
||||
private val plugins = HashSet<Plugin>()
|
||||
private var meta = MetaBuilder()
|
||||
|
||||
public fun properties(action: MetaBuilder.() -> Unit) {
|
||||
@ -20,9 +20,12 @@ public class ContextBuilder(private val parent: Context = Global, public var nam
|
||||
}
|
||||
|
||||
@OptIn(DFExperimental::class)
|
||||
public fun plugin(tag: PluginTag, metaBuilder: MetaBuilder.() -> Unit = {}) {
|
||||
val factory = parent.gatherInSequence<PluginFactory<*>>(PluginFactory.TYPE).values
|
||||
private fun findPluginFactory(tag: PluginTag): PluginFactory<*> =
|
||||
parent.gatherInSequence<PluginFactory<*>>(PluginFactory.TYPE).values
|
||||
.find { it.tag.matches(tag) } ?: error("Can't resolve plugin factory for $tag")
|
||||
|
||||
public fun plugin(tag: PluginTag, metaBuilder: MetaBuilder.() -> Unit = {}) {
|
||||
val factory = findPluginFactory(tag)
|
||||
val plugin = factory.invoke(Meta(metaBuilder), parent)
|
||||
plugins.add(plugin)
|
||||
}
|
||||
@ -36,10 +39,6 @@ public class ContextBuilder(private val parent: Context = Global, public var nam
|
||||
}
|
||||
|
||||
public fun build(): Context {
|
||||
return Context(name.toName(), parent, meta.seal()).apply {
|
||||
this@ContextBuilder.plugins.forEach {
|
||||
plugins.load(it)
|
||||
}
|
||||
}
|
||||
return Context(name.toName(), parent, meta.seal(), plugins)
|
||||
}
|
||||
}
|
@ -16,21 +16,24 @@ public interface PluginFactory<T : Plugin> : Factory<T> {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The manager for plugin system. Should monitor plugin dependencies and locks.
|
||||
*
|
||||
* @property context A context for this plugin manager
|
||||
* @author Alexander Nozik
|
||||
*/
|
||||
public class PluginManager(override val context: Context) : ContextAware, Iterable<Plugin> {
|
||||
public class PluginManager(override val context: Context, plugins: Set<Plugin>) : ContextAware, Iterable<Plugin> {
|
||||
|
||||
//TODO refactor to read-only container
|
||||
|
||||
/**
|
||||
* A set of loaded plugins
|
||||
*/
|
||||
private val plugins = HashSet<Plugin>()
|
||||
private val plugins: HashSet<Plugin> = HashSet(plugins)
|
||||
|
||||
init {
|
||||
plugins.forEach { it.attach(context) }
|
||||
}
|
||||
|
||||
/**
|
||||
* A [PluginManager] of parent context if it is present
|
||||
@ -56,7 +59,6 @@ public class PluginManager(override val context: Context) : ContextAware, Iterab
|
||||
public fun find(inherit: Boolean = true, predicate: (Plugin) -> Boolean): Plugin? =
|
||||
list(inherit).find(predicate)
|
||||
|
||||
|
||||
/**
|
||||
* Find a loaded plugin via its tag
|
||||
*
|
||||
@ -66,7 +68,6 @@ public class PluginManager(override val context: Context) : ContextAware, Iterab
|
||||
public operator fun get(tag: PluginTag, inherit: Boolean = true): Plugin? =
|
||||
find(inherit) { tag.matches(it.tag) }
|
||||
|
||||
|
||||
/**
|
||||
* Find a loaded plugin via its class. This method does not check if the result is unique and just returns first
|
||||
* plugin matching the class condition.
|
||||
@ -96,10 +97,8 @@ public class PluginManager(override val context: Context) : ContextAware, Iterab
|
||||
* @return
|
||||
*/
|
||||
public fun <T : Plugin> load(plugin: T): T {
|
||||
if (context.isActive) error("Can't load plugin into active context")
|
||||
|
||||
if (get(plugin::class, plugin.tag, recursive = false) != null) {
|
||||
error("Plugin of type ${plugin::class} already exists in ${context.name}")
|
||||
error("Plugin with tag ${plugin.tag} already exists in ${context.name}")
|
||||
} else {
|
||||
for (tag in plugin.dependsOn()) {
|
||||
fetch(tag, true)
|
||||
@ -125,8 +124,6 @@ public class PluginManager(override val context: Context) : ContextAware, Iterab
|
||||
* Remove a plugin from [PluginManager]
|
||||
*/
|
||||
public fun remove(plugin: Plugin) {
|
||||
if (context.isActive) error("Can't remove plugin from active context")
|
||||
|
||||
if (plugins.contains(plugin)) {
|
||||
logger.info { "Removing plugin ${plugin.name} from ${context.name}" }
|
||||
plugin.detach()
|
||||
@ -136,7 +133,6 @@ public class PluginManager(override val context: Context) : ContextAware, Iterab
|
||||
|
||||
/**
|
||||
* Get an existing plugin with given meta or load new one using provided factory
|
||||
*
|
||||
*/
|
||||
public fun <T : Plugin> fetch(factory: PluginFactory<T>, recursive: Boolean = true, meta: Meta = Meta.EMPTY): T {
|
||||
val loaded = get(factory.type, factory.tag, recursive)
|
||||
|
@ -45,25 +45,23 @@ public interface Workspace : ContextAware, Provider {
|
||||
* Invoke a task in the workspace utilizing caching if possible
|
||||
*/
|
||||
public fun <R : Any> run(task: Task<R>, config: Meta): DataNode<R> {
|
||||
context.activate(this)
|
||||
try {
|
||||
val model = task.build(this, config)
|
||||
task.validate(model)
|
||||
return task.run(this, model)
|
||||
} finally {
|
||||
context.deactivate(this)
|
||||
}
|
||||
val model = task.build(this, config)
|
||||
task.validate(model)
|
||||
return task.run(this, model)
|
||||
}
|
||||
|
||||
public companion object {
|
||||
public const val TYPE: String = "workspace"
|
||||
public operator fun invoke(parent: Context = Global, block: SimpleWorkspaceBuilder.() -> Unit): SimpleWorkspace =
|
||||
public operator fun invoke(
|
||||
parent: Context = Global,
|
||||
block: SimpleWorkspaceBuilder.() -> Unit,
|
||||
): SimpleWorkspace =
|
||||
SimpleWorkspaceBuilder(parent).apply(block).build()
|
||||
}
|
||||
}
|
||||
|
||||
public fun Workspace.run(task: Task<*>, target: String): DataNode<Any> {
|
||||
val meta = targets[target] ?: error("A target with name $target not found in ${this}")
|
||||
val meta = targets[target] ?: error("A target with name $target not found in $this")
|
||||
return run(task, meta)
|
||||
}
|
||||
|
||||
@ -77,5 +75,5 @@ public fun Workspace.run(task: String, meta: Meta): DataNode<Any> =
|
||||
public fun Workspace.run(task: String, block: MetaBuilder.() -> Unit = {}): DataNode<Any> =
|
||||
run(task, Meta(block))
|
||||
|
||||
public fun <T: Any> Workspace.run(task: Task<T>, metaBuilder: MetaBuilder.() -> Unit = {}): DataNode<T> =
|
||||
public fun <T : Any> Workspace.run(task: Task<T>, metaBuilder: MetaBuilder.() -> Unit = {}): DataNode<T> =
|
||||
run(task, Meta(metaBuilder))
|
Loading…
Reference in New Issue
Block a user