[jboss-jira] [JBoss JIRA] (DROOLS-309) Multiple threads working with traits against same knowledge base hangs

James Myers (JIRA) jira-events at lists.jboss.org
Tue Oct 22 11:32:02 EDT 2013


James Myers created DROOLS-309:
----------------------------------

             Summary: Multiple threads working with traits against same knowledge base hangs
                 Key: DROOLS-309
                 URL: https://issues.jboss.org/browse/DROOLS-309
             Project: Drools
          Issue Type: Quality Risk
      Security Level: Public (Everyone can see)
    Affects Versions: 5.5.0.Final
            Reporter: James Myers
            Assignee: Mark Proctor


In our web system, we are creating new StatefulKnowledgeSession per user session and executing a set of rules containing trait donning.  This starts to hang (seemingly indefinitely) with following type of stack trace (usually initiated from insert/update):

{quote}
   java.lang.Thread.State: RUNNABLE
	at org.drools.core.util.TripleStore.getAll(TripleStore.java:188)
	at org.drools.factmodel.traits.TripleBasedStruct.getTriplesForSubject(TripleBasedStruct.java:165)
	at org.drools.factmodel.traits.ThingorgdroolsfactmodeltraitsTraitSession$ItemWrapperProxyWrapper.hashCode(Unknown Source)
	at org.drools.factmodel.traits.TraitProxy.hashCode(TraitProxy.java:110)
	at org.drools.factmodel.traits.ThingorgdroolsfactmodeltraitsTraitSession$ItemWrapperProxy.hashCode(Unknown Source)
	at org.drools.common.DefaultFactHandle.<init>(DefaultFactHandle.java:110)
	at org.drools.common.DefaultFactHandle.<init>(DefaultFactHandle.java:98)
	at org.drools.common.TraitFactHandle.<init>(TraitFactHandle.java:26)
	at org.drools.reteoo.ReteooFactHandleFactory.newFactHandle(ReteooFactHandleFactory.java:80)
	at org.drools.common.AbstractFactHandleFactory.newFactHandle(AbstractFactHandleFactory.java:68)
	at org.drools.common.AbstractFactHandleFactory.newFactHandle(AbstractFactHandleFactory.java:53)
	at org.drools.common.NamedEntryPoint.createHandle(NamedEntryPoint.java:765)
	at org.drools.common.NamedEntryPoint.insert(NamedEntryPoint.java:301)
	at org.drools.common.AbstractWorkingMemory.insert(AbstractWorkingMemory.java:903)
{quote}

Here is a unit test for org.drools.factmodel.traits.TraitTest.  It's not perfect because it will spawn thread that might never die and may need thread/iteration count increased to fail consistently, but capturing a stack trace a few seconds in should show all threads in "getAll()":

{code}
    @Traitable
    public static class Item {
    	private String id;

    	public String getId() {
    		return id;
    	}

    	public void setId(String id) {
    		this.id = id;
    	}
    }

    public static class TraitRulesThread implements Runnable {
    	int threadIndex;
    	int numRepetitions;
    	StatefulKnowledgeSession ksession;

    	public TraitRulesThread(int threadIndex, int numRepetitions, final StatefulKnowledgeSession ksession) {
    		this.threadIndex = threadIndex;
    		this.numRepetitions = numRepetitions;
    		this.ksession = ksession;
    	}
    	public void run() {
    		for (int repetitionIndex = 0; repetitionIndex < numRepetitions; repetitionIndex++) {
    			final Item i = new Item();
    			i.setId(String.format("testId_%d%d", threadIndex, repetitionIndex));
    			ksession.insert(i);
    			ksession.fireAllRules();
    		}
    	}
    }

    @Test
    public void testMultithreadingTraits() throws InterruptedException {
    	final String s1 = "package test;\n" +
    	"import org.drools.factmodel.traits.TraitTest.Item;\n" +
    	"declare Item end\n" +
    	"declare trait ItemStyle\n" +
    	"	id: String\n" +
    	"	adjustable: boolean\n" +
    	"end\n" +
    	"rule \"Don ItemStyle\"\n" +
    	"	no-loop true\n" +
    	"	when\n" +
    	"		$p : Item ()\n" +
    	"		not ItemStyle ( id == $p.id )\n" +
    	"	then\n" +
    	"		don($p, ItemStyle.class);\n" +
    	"end\n" +
    	"rule \"Item Style - Adjustable\"" +
    	"	no-loop true" +
    	"	when" +
    	"		$style : ItemStyle ( !adjustable )" +
    	"		Item (" +
    	"			id == $style.id " +
    	"		)" +
    	"	then" +
    	"		modify($style) {" +
    	"			setAdjustable(true)" +
    	"		};" +
    	"end";
    	final KnowledgeBase kbase = getKnowledgeBaseFromString(s1);

    	// might need to tweak these numbers.  often works with 7-10,100,60, but often fails 15-20,100,60
    	int MAX_THREADS = 20;
    	int MAX_REPETITIONS = 100;
    	int MAX_WAIT_SECONDS = 60;

    	final ExecutorService executorService = Executors.newFixedThreadPool(MAX_THREADS);
    	for (int threadIndex = 0; threadIndex < MAX_THREADS; threadIndex++) {
    		executorService.execute(new TraitRulesThread(threadIndex, MAX_REPETITIONS, kbase.newStatefulKnowledgeSession()));
    	}

    	executorService.shutdown();
    	executorService.awaitTermination(MAX_WAIT_SECONDS, TimeUnit.SECONDS);
    	final List<Runnable> queuedTasks = executorService.shutdownNow();

    	assertEquals(0, queuedTasks.size());
    	assertEquals(true, executorService.isTerminated());
    }
{code}

--
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators
For more information on JIRA, see: http://www.atlassian.com/software/jira


More information about the jboss-jira mailing list