Skip to content
This repository was archived by the owner on Mar 24, 2025. It is now read-only.

Commit 6039007

Browse files
author
Denes Bodo
committed
OOZIE-3715 Fix fork out more than one transitions submit , one transition submit fail can't execute KillXCommand (chenhd via dionusos)
1 parent d4e3673 commit 6039007

File tree

4 files changed

+151
-0
lines changed

4 files changed

+151
-0
lines changed

core/src/main/java/org/apache/oozie/command/wf/SignalXCommand.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -549,6 +549,9 @@ public void startForkedActions(List<WorkflowActionBean> workflowActionBeanListFo
549549
if (context.getJobStatus() != null && context.getJobStatus().equals(Job.Status.FAILED)) {
550550
LOG.warn("Action has failed, failing job" + context.getAction().getId());
551551
new ActionStartXCommand(context.getAction().getId(), null).failJob(context);
552+
// Fork out more than one transitions, one should be transitions,
553+
// one submit fail can't execute KillXCommand
554+
queue(new KillXCommand(context.getWorkflow().getId()));
552555
updateList.add(new UpdateEntry<WorkflowActionQuery>(WorkflowActionQuery.UPDATE_ACTION_START,
553556
(WorkflowActionBean) context.getAction()));
554557
if (context.isShouldEndWF()) {

core/src/test/java/org/apache/oozie/ForTestingActionExecutor.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,9 @@ public void start(Context context, WorkflowAction action) throws ActionExecutorE
5959
if ("start.error".equals(error)) {
6060
throw new ActionExecutorException(ActionExecutorException.ErrorType.ERROR, TEST_ERROR, "start");
6161
}
62+
if ("start.fail".equals(error)) {
63+
throw new ActionExecutorException(ActionExecutorException.ErrorType.FAILED, TEST_ERROR, "start");
64+
}
6265
String externalStatus = eConf.getChild("external-status", ns).getText().trim();
6366
Element externalChildIds = eConf.getChild("external-childIds", ns);
6467

core/src/test/java/org/apache/oozie/command/wf/TestSignalXCommand.java

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import java.io.Writer;
2929
import java.net.URI;
3030
import java.nio.charset.StandardCharsets;
31+
import java.util.List;
3132
import java.util.Properties;
3233

3334
import org.apache.hadoop.conf.Configuration;
@@ -39,21 +40,31 @@
3940
import org.apache.log4j.SimpleLayout;
4041
import org.apache.log4j.WriterAppender;
4142
import org.apache.oozie.DagEngine;
43+
import org.apache.oozie.ForTestingActionExecutor;
4244
import org.apache.oozie.WorkflowActionBean;
4345
import org.apache.oozie.client.OozieClient;
4446
import org.apache.oozie.client.WorkflowAction;
4547
import org.apache.oozie.client.WorkflowJob;
48+
import org.apache.oozie.executor.jpa.WorkflowActionQueryExecutor;
49+
import org.apache.oozie.executor.jpa.WorkflowActionsGetForJobJPAExecutor;
4650
import org.apache.oozie.executor.jpa.WorkflowJobQueryExecutor;
51+
import org.apache.oozie.executor.jpa.WorkflowJobsGetForPurgeJPAExecutor;
4752
import org.apache.oozie.local.LocalOozie;
4853
import org.apache.oozie.service.CallableQueueService;
4954
import org.apache.oozie.service.ConfigurationService;
5055
import org.apache.oozie.service.ExtendedCallableQueueService;
5156
import org.apache.oozie.service.Services;
57+
import org.apache.oozie.service.SchemaService;
58+
import org.apache.oozie.service.LiteWorkflowStoreService;
59+
import org.apache.oozie.service.ActionService;
60+
import org.apache.oozie.service.JPAService;
5261
import org.apache.oozie.test.XDataTestCase;
5362
import org.apache.oozie.util.IOUtils;
5463
import org.apache.oozie.util.XConfiguration;
5564
import org.apache.oozie.workflow.lite.LiteWorkflowAppParser;
5665

66+
import javax.persistence.EntityManager;
67+
5768
public class TestSignalXCommand extends XDataTestCase {
5869

5970
private Services services;
@@ -410,4 +421,137 @@ public boolean evaluate() throws Exception {
410421
.getStatus(),
411422
WorkflowJob.Status.SUCCEEDED);
412423
}
424+
425+
/**
426+
* Test : fork parallel submit, one transition fail, and the job is failed but the other transition
427+
* always RUNNING or PREP.
428+
* verify the PreconditionException is thrown when action2 = RUNNING or PREP and job = FAIL
429+
*
430+
*/
431+
public void testForkParallelSubmitFail() throws Exception {
432+
_testForkSubmitRunFail(true);
433+
}
434+
435+
/**
436+
* Test : fork serial submit, one transition fail, and the job is failed but the other transition
437+
* always RUNNING or PREP.
438+
* verify the PreconditionException is thrown when action2 = RUNNING or PREP and job = FAIL
439+
*
440+
*/
441+
public void testForkSerialSubmitFail() throws Exception {
442+
_testForkSubmitRunFail(false);
443+
}
444+
445+
/**
446+
* Test : fork parallel submit, one transition fail, and the job is failed but the other transition
447+
* always RUNNING or PREP.
448+
* verify the PreconditionException is thrown when action2 = RUNNING or PREP and job = FAIL
449+
*
450+
* @param isForkParallelSubmit ("ture" or "fail")
451+
*/
452+
private void _testForkSubmitRunFail(boolean isForkParallelSubmit) throws Exception {
453+
services.destroy();
454+
setSystemProperty(SchemaService.WF_CONF_EXT_SCHEMAS, "wf-ext-schema.xsd");
455+
setSystemProperty(LiteWorkflowStoreService.CONF_USER_RETRY_ERROR_CODE_EXT, ForTestingActionExecutor.TEST_ERROR);
456+
services = new Services();
457+
services.init();
458+
services.get(ActionService.class).registerAndInitExecutor(ForTestingActionExecutor.class);
459+
ConfigurationService.setBoolean(SignalXCommand.FORK_PARALLEL_JOBSUBMISSION, isForkParallelSubmit);
460+
461+
String workflowUri = getTestCaseFileUri("workflow.xml");
462+
//@formatter:off
463+
String appXml = "<workflow-app xmlns=\"uri:oozie:workflow:1.0\" name=\"wf-fork-submit\">\n" +
464+
" <start to=\"fork1\"/>\n" +
465+
" <fork name=\"fork1\">\n" +
466+
" <path start=\"action_to_be_failed\"/>\n" +
467+
" <path start=\"action_to_be_succeeded_or_killed\"/>\n" +
468+
" </fork>\n" +
469+
" <action name=\"action_to_be_failed\">\n" +
470+
" <test xmlns=\"uri:test\">\n" +
471+
" <signal-value>${wf:conf('signal-value')}</signal-value>\n" +
472+
" <external-status>${wf:conf('external-status')}</external-status>\n" +
473+
" <error>${wf:conf('error')}</error>\n" +
474+
" <avoid-set-execution-data>${wf:conf('avoid-set-execution-data')}</avoid-set-execution-data>\n" +
475+
" <avoid-set-end-data>${wf:conf('avoid-set-end-data')}</avoid-set-end-data>\n" +
476+
" <running-mode>${wf:conf('running-mode')}</running-mode>\n" +
477+
" </test>\n" +
478+
" <ok to=\"join1\"/>\n" +
479+
" <error to=\"kill\"/>\n" +
480+
" </action>\n" +
481+
" <action name=\"action_to_be_succeeded_or_killed\">\n" +
482+
" <test xmlns=\"uri:test\">\n" +
483+
" <signal-value>based_on_action_status</signal-value>\n" +
484+
" <external-status>ok</external-status>\n" +
485+
" <error>ok</error>\n" +
486+
" <avoid-set-execution-data>true</avoid-set-execution-data>\n" +
487+
" <avoid-set-end-data>false</avoid-set-end-data>\n" +
488+
" <running-mode>async</running-mode>\n" +
489+
" </test>\n" +
490+
" <ok to=\"join1\"/>\n" +
491+
" <error to=\"kill\"/>\n" +
492+
" </action>\n" +
493+
" <join name=\"join1\" to=\"end\"/>\n" +
494+
" <kill name=\"kill\">\n" +
495+
" <message>killed</message>\n" +
496+
" </kill>\n" +
497+
" <end name=\"end\"/>\n" +
498+
"</workflow-app>";
499+
//@Formatter:on
500+
writeToFile(appXml, workflowUri);
501+
502+
final DagEngine engine = new DagEngine("u");
503+
504+
Configuration conf = new Configuration();
505+
conf.set(OozieClient.APP_PATH, workflowUri);
506+
conf.set(OozieClient.USER_NAME, getTestUser());
507+
conf.set(OozieClient.LOG_TOKEN, "t");
508+
conf.set("error", "start.fail");
509+
conf.set("external-status", "error");
510+
conf.set("signal-value", "based_on_action_status");
511+
512+
final String jobId = engine.submitJob(conf, true);
513+
final WorkflowActionsGetForJobJPAExecutor actionsGetExecutor = new WorkflowActionsGetForJobJPAExecutor(jobId);
514+
final JPAService jpaService = Services.get().get(JPAService.class);
515+
516+
waitFor(30 * 1000, new Predicate() {
517+
public boolean evaluate() throws Exception {
518+
return WorkflowJob.Status.FAILED.equals(engine.getJob(jobId).getStatus());
519+
}
520+
});
521+
522+
// wait for execute KillXCommand, and all actions has finished
523+
waitFor(30 * 1000, new Predicate() {
524+
public boolean evaluate() throws Exception {
525+
List<WorkflowActionBean> actions = jpaService.execute(actionsGetExecutor);
526+
for (WorkflowActionBean action : actions) {
527+
if (WorkflowAction.Status.PREP.equals(action.getStatus()) ||
528+
WorkflowAction.Status.RUNNING.equals(action.getStatus()) ){
529+
return false;
530+
}
531+
}
532+
return true;
533+
}
534+
});
535+
536+
List<WorkflowActionBean> actions = jpaService.execute(actionsGetExecutor);
537+
assertEquals("action size [" + actions.size() + "] had incorrect", 4, actions.size());
538+
539+
for (WorkflowActionBean action : actions) {
540+
if ("action_to_be_failed".equals(action.getName())){
541+
assertEquals("action [" + action.getName() + "] had incorrect status",
542+
WorkflowAction.Status.FAILED, action.getStatus());
543+
}
544+
545+
if ("action_to_be_succeeded_or_killed".equals(action.getName())){
546+
// 1.The "action_to_be_failed" action submit fail, and the "action_to_be_succeeded_or_killed" action
547+
// has finished, so the "action_to_be_succeeded_or_killed" action should be OK
548+
// 2.The "action_to_be_failed" action submit fail, and the "action_to_be_succeeded_or_killed" action is
549+
// PREP or RUNNING, so the "action_to_be_succeeded_or_killed" action should be KILLED
550+
if (!WorkflowAction.Status.KILLED.equals(action.getStatus()) &&
551+
!WorkflowAction.Status.OK.equals(action.getStatus())) {
552+
fail("Unexpected action [" + action.getName() + "] with status [" + action.getStatus() + "]");
553+
}
554+
}
555+
}
556+
}
413557
}

release-log.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
-- Oozie 5.3.0 release (trunk - unreleased)
22

3+
OOZIE-3715 Fix fork out more than one transitions submit , one transition submit fail can't execute KillXCommand (chenhd via dionusos)
34
OOZIE-3716 Invocation of Main class completed Message is skipped when LauncherSecurityManager calls system exit (khr9603 via dionusos)
45
OOZIE-3695 [sharelib-hive2] Fix current SpotBugs discovered issues in Oozie's sharelib-hive2 module (jmakai via dionusos)
56
OOZIE-3694 [sharelib-hive] Fix current SpotBugs discovered issues in Oozie's sharelib-hive module (jmakai via dionusos)

0 commit comments

Comments
 (0)