Skip to content

Commit

Permalink
Add nflow.autoinit parameter, defaults to true
Browse files Browse the repository at this point in the history
Controls workflow definitions fetch from the database during Spring context load. This commit fixes problem with server in some cases starting before definitions are initialized from the database.
  • Loading branch information
ttiurani committed Nov 17, 2017
1 parent 551b88b commit e5f5aba
Show file tree
Hide file tree
Showing 6 changed files with 34 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,30 +2,43 @@

import static org.slf4j.LoggerFactory.getLogger;

import java.io.IOException;
import java.util.concurrent.ThreadFactory;

import javax.inject.Inject;

import org.slf4j.Logger;
import org.springframework.context.SmartLifecycle;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;

import io.nflow.engine.internal.executor.WorkflowDispatcher;
import io.nflow.engine.service.WorkflowDefinitionService;

@Component
public class WorkflowLifecycle implements SmartLifecycle {
private static final Logger logger = getLogger(WorkflowLifecycle.class);

private final WorkflowDefinitionService workflowDefinitions;
private final WorkflowDispatcher dispatcher;
private final boolean autoStart;
private final Thread dispatcherThread;

@Inject
public WorkflowLifecycle(WorkflowDispatcher dispatcher, @NFlow ThreadFactory nflowThreadFactory, Environment env) {
public WorkflowLifecycle(WorkflowDefinitionService workflowDefinitions, WorkflowDispatcher dispatcher,
@NFlow ThreadFactory nflowThreadFactory, Environment env) throws IOException, ReflectiveOperationException {
this.dispatcher = dispatcher;
this.workflowDefinitions = workflowDefinitions;
if (env.getRequiredProperty("nflow.autoinit", Boolean.class)) {
this.workflowDefinitions.postProcessWorkflowDefinitions();
} else {
logger.info("nFlow engine autoinit disabled (system property nflow.autoinit=false)");
}
autoStart = env.getRequiredProperty("nflow.autostart", Boolean.class);
dispatcherThread = nflowThreadFactory.newThread(dispatcher);
dispatcherThread.setName("nflow-dispatcher");
if (!autoStart) {
getLogger(WorkflowLifecycle.class).info("nFlow engine autostart disabled (system property nflow.autostart=false)");
logger.info("nFlow engine autostart disabled (system property nflow.autostart=false)");
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ public class WorkflowDispatcher implements Runnable {
private final long sleepTimeMillis;
private final int stuckThreadThresholdSeconds;
private final Random rand = new Random();
private final boolean autoInit;

@Inject
@SuppressFBWarnings(value = "WEM_WEAK_EXCEPTION_MESSAGING", justification = "Transaction support exception message is fine")
Expand All @@ -52,6 +53,8 @@ public WorkflowDispatcher(WorkflowInstanceExecutor executor, WorkflowInstanceDao
this.executorDao = executorDao;
this.sleepTimeMillis = env.getRequiredProperty("nflow.dispatcher.sleep.ms", Long.class);
this.stuckThreadThresholdSeconds = env.getRequiredProperty("nflow.executor.stuckThreadThreshold.seconds", Integer.class);
this.autoInit = env.getRequiredProperty("nflow.autoinit", Boolean.class);

if (!executorDao.isTransactionSupportEnabled()) {
throw new BeanCreationException("Transaction support must be enabled");
}
Expand All @@ -61,7 +64,9 @@ public WorkflowDispatcher(WorkflowInstanceExecutor executor, WorkflowInstanceDao
public void run() {
logger.info("Starting.");
try {
workflowDefinitions.postProcessWorkflowDefinitions();
if (!autoInit) {
workflowDefinitions.postProcessWorkflowDefinitions();
}
while (!shutdownRequested) {
try {
executor.waitUntilQueueSizeLowerThanThreshold(executorDao.getMaxWaitUntil());
Expand Down
1 change: 1 addition & 0 deletions nflow-engine/src/main/resources/nflow-engine.properties
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
nflow.autoinit=true
nflow.autostart=true
nflow.executor.group=nflow
nflow.executor.timeout.seconds=900
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import java.io.IOException;
import java.util.concurrent.ThreadFactory;

import org.junit.Before;
Expand All @@ -17,6 +18,7 @@
import org.springframework.core.env.Environment;

import io.nflow.engine.internal.executor.WorkflowDispatcher;
import io.nflow.engine.service.WorkflowDefinitionService;

@RunWith(MockitoJUnitRunner.class)
public class WorkflowLifecycleTest {
Expand All @@ -29,14 +31,17 @@ public class WorkflowLifecycleTest {
private Environment env;
@Mock
private Thread dispatcherThread;
@Mock
private WorkflowDefinitionService workflowDefinitions;

private WorkflowLifecycle lifecycle;

@Before
public void setup() {
public void setup() throws IOException, ReflectiveOperationException {
when(env.getRequiredProperty("nflow.autoinit", Boolean.class)).thenReturn(TRUE);
when(env.getRequiredProperty("nflow.autostart", Boolean.class)).thenReturn(TRUE);
when(threadFactory.newThread(dispatcher)).thenReturn(dispatcherThread);
lifecycle = new WorkflowLifecycle(dispatcher, threadFactory, env);
lifecycle = new WorkflowLifecycle(workflowDefinitions, dispatcher, threadFactory, env);
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ public class WorkflowDispatcherTest {

@Before
public void setup() {
env.setProperty("nflow.autoinit", "true");
env.setProperty("nflow.dispatcher.sleep.ms", "0");
env.setProperty("nflow.dispatcher.executor.queue.wait_until_threshold", "0");
env.setProperty("nflow.illegal.state.change.action", "ignore");
Expand Down
10 changes: 4 additions & 6 deletions nflow-tests/src/test/java/io/nflow/tests/SkipAutoStartTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,12 @@

public class SkipAutoStartTest extends AbstractNflowTest {

// Because nflow.db.create_on_startup is false, no tables are created, which
// causes failures if SQL statements are issued during bean initialization.
// We need a valid database connection because connection to the database using
// a database driver is done during bean initialization in the
// DatabaseConfiguration class.
// When nflow.autoinit, nflow.autostart and nflow.db.create_on_startup are false
// no database access should happen. This test fails if SQL statements are
// issued during bean initialization.
@ClassRule
public static NflowServerRule server = new NflowServerRule.Builder()
.prop("nflow.autostart", "false").prop("nflow.db.create_on_startup", "false")
.prop("nflow.autoinit", "false").prop("nflow.autostart", "false").prop("nflow.db.create_on_startup", "false")
.build();

public SkipAutoStartTest() {
Expand Down

0 comments on commit e5f5aba

Please sign in to comment.