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

Uses CustomEvents within ImportJobs #1961

Merged
merged 22 commits into from
Apr 4, 2024
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
16ad4d9
Utilizes the CustomEvents framework in ImportJobs
andyHa Apr 2, 2024
c89ace5
Fixes a typo
andyHa Apr 2, 2024
65497f9
Merge branch 'feature/aha/import-scripting-2' into feature/aha/import…
andyHa Apr 2, 2024
48306b8
Completes a renaming of the previous PR
andyHa Apr 2, 2024
3dbcb22
Defines and invokes a bunch of events within ImportHandlers
andyHa Apr 2, 2024
06f6237
Fixes a typo
andyHa Apr 2, 2024
25c15fd
Merge branch 'develop' into feature/aha/import-scripting-3
andyHa Apr 3, 2024
f9fb749
Moves the OnLoadEvent into a proper location
andyHa Apr 3, 2024
271213a
Permits to properly use the registry
andyHa Apr 3, 2024
fc3047c
Properly sorts the available dispatchers
andyHa Apr 3, 2024
c83d2a9
Makes the ImportJobStartedEvent less generic.
andyHa Apr 3, 2024
ecc5414
Introduces a BeforeCreateOrUpdateEntityEvent
andyHa Apr 3, 2024
19f8fff
Adds a simple toString for BeforeFindEvent
andyHa Apr 3, 2024
05a62c6
Properly handles the case that no ScriptableEventDispatcher is present
andyHa Apr 3, 2024
0296bdf
Adds a proper framework annotation for an entity
andyHa Apr 3, 2024
17562fb
Unifies event naming and splits the OnLoadEvent to BeforeLoadEvent an…
andyHa Apr 3, 2024
08ac534
Permits to access some methods via noodle scripts
idlira Apr 3, 2024
8c96f54
Permits to access some Context methods via noodle scripts
idlira Apr 3, 2024
d372110
Removes a redundant cast - now properly supported by Noodle
andyHa Apr 3, 2024
b0ffd27
Merge branch 'feature/aha/import-scripting-3' of https://github.com/s…
andyHa Apr 3, 2024
9205f2a
Uses wildcard for Context methods in sandbox rules
idlira Apr 4, 2024
5724ab5
Bumps sirius libs
idlira Apr 4, 2024
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
5 changes: 5 additions & 0 deletions src/main/java/sirius/biz/importer/BaseImportHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,11 @@ protected E load(Context data, Mapping... mappings) {
protected E load(Context data, E entity, Mapping... mappings) {
Arrays.stream(mappings).forEach(mapping -> loadMapping(entity, mapping, data));

if (context.getEventDispatcher().isActive()) {
context.getEventDispatcher()
.handleEvent(new OnLoadEvent<E>(entity, data, Arrays.stream(mappings).toList(), context));
}

enforcePostLoadConstraints(entity);

return entity;
Expand Down
33 changes: 33 additions & 0 deletions src/main/java/sirius/biz/importer/BeforeFindEvent.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* Made with all the love in the world
* by scireum in Remshalden, Germany
*
* Copyright by scireum GmbH
* http://www.scireum.de - info@scireum.de
*/

package sirius.biz.importer;

import sirius.db.mixing.Entity;
import sirius.kernel.commons.Context;

/**
* Triggered within {@link sirius.biz.importer.ImportHandler#tryFind(Context)} before the entity is actually being
* looked up.
*
* @param <E> the type of entity being looked up
*/
public class BeforeFindEvent<E extends Entity> extends ContextScriptableEvent<E> {

/**
* Creates a new event for the given entity type, context and import context.
*
* @param entityType the type of entities being looked up
* @param context the context to read data from. Note that this can and should be modified by the handler,
* as this is the whole purpose of this event anyway.
* @param importerContext the import context which can be used to access other handlers / the importer itself
*/
public BeforeFindEvent(Class<E> entityType, Context context, ImporterContext importerContext) {
super(entityType, context, importerContext);
}
}
61 changes: 61 additions & 0 deletions src/main/java/sirius/biz/importer/ContextScriptableEvent.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/*
* Made with all the love in the world
* by scireum in Remshalden, Germany
*
* Copyright by scireum GmbH
* http://www.scireum.de - info@scireum.de
*/

package sirius.biz.importer;

import sirius.biz.scripting.TypedScriptableEvent;
import sirius.kernel.commons.Context;

/**
* Provides a base implementation for all events which are scriptable and have a context / import context
*
* @param <E> the generic type of entities being handled
*/
public abstract class ContextScriptableEvent<E> extends TypedScriptableEvent<E> {

private final Class<E> entityType;
private final Context context;
private final ImporterContext importerContext;

/**
* Creates a new event for the given entity type, context and import context.
*
* @param entityType the type of entity being handled
* @param context the context to read data from. Note that this can and should be modified by the handler,
* as this is the whole purpose of this event anyway.
* @param importerContext the import context which can be used to access other handlers / the importer itself
*/
@SuppressWarnings("AssignmentOrReturnOfFieldWithMutableType")
protected ContextScriptableEvent(Class<E> entityType, Context context, ImporterContext importerContext) {
this.entityType = entityType;
this.context = context;
this.importerContext = importerContext;
}

/**
* Returns the context which contains the data of the current event.
* <p>
* Note that this is mutable by design, as the handler will most probably want to modify the context
* before it is processed by the import handler
*
* @return the context containing the actual data being imported
*/
@SuppressWarnings("AssignmentOrReturnOfFieldWithMutableType")
public Context getContext() {
return context;
}

public ImporterContext getImporterContext() {
return importerContext;
}

@Override
public Class<E> getType() {
return entityType;
}
}
11 changes: 11 additions & 0 deletions src/main/java/sirius/biz/importer/ImporterContext.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import sirius.biz.jobs.batch.ImportJob;
import sirius.biz.scripting.ScriptableEventDispatcher;
import sirius.db.jdbc.batch.BatchContext;
import sirius.db.mixing.BaseEntity;
import sirius.kernel.commons.Context;
Expand Down Expand Up @@ -39,6 +40,8 @@ public class ImporterContext {
private static List<ImportHandlerFactory> factories;

private final Importer importer;
private ScriptableEventDispatcher eventDispatcher;

private BatchContext batchContext;

private final Map<Class<?>, ImportHandler<?>> handlers = new HashMap<>();
Expand Down Expand Up @@ -241,4 +244,12 @@ public BatchContext getBatchContext() {

return batchContext;
}

public ScriptableEventDispatcher getEventDispatcher() {
return eventDispatcher;
}

public void setEventDispatcher(ScriptableEventDispatcher eventDispatcher) {
this.eventDispatcher = eventDispatcher;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,14 @@ protected void collectDefaultExportableMappings(BiConsumer<Integer, Mapping> col
// via @Exportable
}

@SuppressWarnings("unchecked")
@Override
public final Optional<E> tryFind(Context data) {
if (context.getEventDispatcher().isActive()) {
context.getEventDispatcher()
.handleEvent(new BeforeFindEvent<E>((Class<E>) descriptor.getType(), data, context));
}

return findByExample(data);
}

Expand Down
52 changes: 52 additions & 0 deletions src/main/java/sirius/biz/importer/OnLoadEvent.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
* Made with all the love in the world
* by scireum in Remshalden, Germany
*
* Copyright by scireum GmbH
* http://www.scireum.de - info@scireum.de
*/

package sirius.biz.importer;

import sirius.db.mixing.BaseEntity;
import sirius.db.mixing.Entity;
import sirius.db.mixing.Mapping;
import sirius.kernel.commons.Context;

import java.util.Collections;
import java.util.List;

/**
* Triggered within {@link sirius.biz.importer.ImportHandler#load(Context, BaseEntity)} in order to update an entity
* using the given context.
*
* @param <E> the type of entity being updated
*/
public class OnLoadEvent<E extends Entity> extends ContextScriptableEvent<E> {
sabieber marked this conversation as resolved.
Show resolved Hide resolved
private final E entity;
private final List<Mapping> mappingsToLoad;

/**
* Creates a new event for the given entity
*
* @param entity the entity to update
* @param context the context to read data from. Note that this can and should be modified by the handler,
* as this is the whole purpose of this event anyway.
* @param mappingsToLoad the mappings to load from the given context
* @param importerContext the import context which can be used to access other handlers / the importer itself
*/
@SuppressWarnings("unchecked")
public OnLoadEvent(E entity, Context context, List<Mapping> mappingsToLoad, ImporterContext importerContext) {
super((Class<E>) entity.getClass(), context, importerContext);
this.entity = entity;
this.mappingsToLoad = Collections.unmodifiableList(mappingsToLoad);
}

public E getEntity() {
return entity;
}

public List<Mapping> getMappingsToLoad() {
return mappingsToLoad;
}
}
6 changes: 6 additions & 0 deletions src/main/java/sirius/biz/importer/SQLEntityImportHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -153,8 +153,14 @@ public E load(Context data, E entity) {
return load(data, entity, mappingsToLoad);
}

@SuppressWarnings("unchecked")
@Override
public Optional<E> tryFind(Context data) {
if (context.getEventDispatcher().isActive()) {
context.getEventDispatcher()
.handleEvent(new BeforeFindEvent<E>((Class<E>) descriptor.getType(), data, context));
}

E example = loadForFind(data);
return tryFindByExample(example);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,17 @@
package sirius.biz.jobs.batch;

import sirius.biz.cluster.work.DistributedTaskExecutor;
import sirius.biz.jobs.params.Parameter;
import sirius.biz.jobs.params.SelectStringParameter;
import sirius.biz.process.PersistencePeriod;
import sirius.biz.process.ProcessContext;
import sirius.biz.scripting.ScriptableEvents;
import sirius.kernel.di.Injector;
import sirius.kernel.di.std.Part;

import java.util.HashMap;
import java.util.Map;
import java.util.function.Consumer;

/**
* Provides a base implementation for batch jobs which are executed by the {@link ImportBatchProcessTaskExecutor}.
Expand All @@ -28,9 +37,41 @@ public String queueName() {
}
}

/**
* Permits selecting the {@link sirius.biz.scripting.ScriptableEventDispatcher} to use for this import.
*/
public static final Parameter<String> DISPATCHER_PARAMETER;

static {
SelectStringParameter dispatcherParameter = new SelectStringParameter("eventDispatcher", "$ImportBatchProcessFactory.eventDispatcher");
dispatcherParameter.markRequired();
dispatcherParameter.withDescription("$ImportBatchProcessFactory.eventDispatcher.helpImportBatchProcessFactory.eventDispatcher.help");
dispatcherParameter.withEntriesProvider(() -> {
Map<String, String> eventDispatchers = new HashMap<>();
ScriptableEvents scriptableEvents = Injector.context().getPart(ScriptableEvents.class);
if (scriptableEvents != null) {
scriptableEvents.fetchDispatchersForCurrentTenant()
.forEach(dispatcher -> eventDispatchers.put(dispatcher, dispatcher));
}
return eventDispatchers;
});

DISPATCHER_PARAMETER = dispatcherParameter.build();
}

@Part
private ScriptableEvents scriptableEvents;

@Override
protected abstract ImportJob createJob(ProcessContext process);

@Override
protected void collectParameters(Consumer<Parameter<?>> parameterCollector) {
if (scriptableEvents.fetchDispatchersForCurrentTenant().size() > 1) {
parameterCollector.accept(DISPATCHER_PARAMETER);
}
}

@Override
protected Class<? extends DistributedTaskExecutor> getExecutor() {
return ImportBatchProcessTaskExecutor.class;
Expand All @@ -45,5 +86,4 @@ public String getIcon() {
protected PersistencePeriod getPersistencePeriod() {
return PersistencePeriod.SIX_YEARS;
}

}
18 changes: 17 additions & 1 deletion src/main/java/sirius/biz/jobs/batch/ImportJob.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,11 @@
import sirius.biz.importer.Importer;
import sirius.biz.process.ProcessContext;
import sirius.biz.process.logs.ProcessLog;
import sirius.biz.scripting.ScriptableEventDispatcher;
import sirius.biz.scripting.ScriptableEvents;
import sirius.db.mixing.BaseEntity;
import sirius.db.mixing.types.BaseEntityRef;
import sirius.kernel.di.std.Part;
import sirius.kernel.health.Exceptions;

import java.io.IOException;
Expand All @@ -29,6 +32,9 @@ public abstract class ImportJob extends BatchJob {
*/
protected final Importer importer;

@Part
private static ScriptableEvents scriptableEvents;

/**
* Creates a new job for the given process context.
*
Expand All @@ -37,6 +43,16 @@ public abstract class ImportJob extends BatchJob {
protected ImportJob(ProcessContext process) {
super(process);
this.importer = new Importer(process.getTitle());

ScriptableEventDispatcher dispatcher = obtainEventDispatcher(process);
this.importer.getContext().setEventDispatcher(dispatcher);

dispatcher.handleEvent(new ImportJobStartedEvent<>(this, process));
}

private ScriptableEventDispatcher obtainEventDispatcher(ProcessContext process) {
String dispatcher = process.getParameter(ImportBatchProcessFactory.DISPATCHER_PARAMETER).orElse(null);
return scriptableEvents.fetchDispatcherForCurrentTenant(dispatcher);
}

/**
Expand All @@ -52,7 +68,7 @@ protected ImportJob(ProcessContext process) {
* @param owner the entity which contains the reference
* @param ref the reference which is either to be filled or verified that it points to <tt>target</tt>
* @param target the target the reference must point to
* @param <E> the generic type the the parent being referenced
* @param <E> the generic type the parent being referenced
* @param <I> the type of the id column of E
* @throws sirius.kernel.health.HandledException if the entities do no match
* @see BaseEntityRef#hasWriteOnceSemantics
Expand Down
51 changes: 51 additions & 0 deletions src/main/java/sirius/biz/jobs/batch/ImportJobStartedEvent.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
* Made with all the love in the world
* by scireum in Remshalden, Germany
*
* Copyright by scireum GmbH
* http://www.scireum.de - info@scireum.de
*/

package sirius.biz.jobs.batch;

import sirius.biz.process.ProcessContext;
import sirius.biz.scripting.TypedScriptableEvent;

/**
* Signals that an {@link ImportJob} has been started.
* <p>
* This might be used to perform some preparation steps like downloading the file to import into the work directory.
*
* @param <T> the import job type being started
*/
public class ImportJobStartedEvent<T> extends TypedScriptableEvent<T> {

private final T job;
private final ProcessContext process;

/**
* Creates a new event for the given job and process.
*
* @param job the job being started
* @param process the process which has been started for the job
*/
public ImportJobStartedEvent(T job, ProcessContext process) {
super();
this.job = job;
this.process = process;
}

public T getJob() {
return job;
}

public ProcessContext getProcess() {
return process;
}

@SuppressWarnings("unchecked")
@Override
public Class<T> getType() {
return (Class<T>) job.getClass();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ protected void collectParameters(Consumer<Parameter<?>> parameterCollector) {
if (UserContext.getCurrentUser().hasPermission(FEATURE_BYPASS_PROCESS_LOG_LIMITS)) {
parameterCollector.accept(LIMIT_LOG_MESSAGES_PARAMETER);
}

super.collectParameters(parameterCollector);
}

/**
Expand Down
Loading