What features to implement next?

66 views
Skip to first unread message

Esko Luontola

unread,
Feb 17, 2013, 4:45:42 PM2/17/13
to jumi-tes...@googlegroups.com
What are to you the most important features that the Jumi test runner
does not yet do? Jumi is starting to be at a point where the next
features can be implemented in almost any order, so please tell me about
your needs and I may prioritize them higher.

I did some asking around at my work place, and the need of a GUI for
showing the results came at the top place. People want to be able to
press a button in their IDE and see the results graphically. I'm also
leaning towards that.

I've listed a bunch of planned features at
https://github.com/orfjackal/jumi/blob/master/ROADMAP.txt

My current plan is to first implement the following features in this order:

#1: Show a progress meter when running the suite
- Usability improvement. Lets you notice if the tests are stuck or
slower than usual.

#2: Ignoring tests
- Basic feature of all test runners. Pretty much the last feature
that the JUnit test runner supports but Jumi doesn't. Useful for ATDD.

#3: Communicating with the daemon process over memory-mapped files
- Important infrastructure change. Prerequisite for quite many other
features.

#4: Persistent daemon process
- Speeds up the tests by reusing the JVM for running the test.
- Depends on #3

#5: Caching library JARs
- Speeds up the tests by removing class loader overhead and by
letting the JIT compiler kick in. See
http://blog.orfjackal.net/2013/02/faster-junit-tests-with-jumi-test.html
- Depends on #4

#6: GUI for showing test results
- Usability improvement. Lets you see test results in real time,
before a test ends. Lets you decide whether to show or hide passing
tests after running them.
- Swing-based user interface that shows the test results of all
suites, regardless of who started them (IDE, build tool, whatever).
- Depends on #3

Out of these #1, #2 and #5 should be quite quick to implement. #3 and #4
are of medium effort and I'll probably need to do some spiking for #3 to
learn more about MMFs. #5 has high potential for exposing issues with
class loader leaks, so it's good to implement it early to learn some
unknown unknowns. #6 may potentially take as much time as allowed, so
I'll try to avoid gold plating and at first release a really basic GUI.

--
Esko Luontola
www.orfjackal.net

deakblue

unread,
Apr 20, 2013, 3:38:07 AM4/20/13
to jumi-tes...@googlegroups.com

I would like to be able to name the Threads in Jumi-Actors.  I could override the ThreadFactory to give the threads names there, but that's somewhat far away from the action.  Otherwise, I could insert a setName into the execution, but that seems awkward.  My thought was at "StartActorThread(String name)."

Is this possible or a bad idea?

Also, Jumi actors is still awesome.

Esko Luontola

unread,
Apr 20, 2013, 5:15:56 PM4/20/13
to jumi-tes...@googlegroups.com
deakblue wrote on 20.4.2013 10:38:
> My thought was at "StartActorThread(String name)."
>
> Is this possible or a bad idea?

Thanks for your feedback. Seems like a good idea. Could you tell a bit
more about your use case? How would you name the threads in your
application? Please give some concrete examples.

I did a search of how I'm using Jumi Actors inside Jumi Test Runner. At
the moment I'm only creating one thread, so I could use a hard-coded
thread name. But I can envision having multiple threads of a similar
kind, in which case I would like unique names using a number sequence
(similar to how Java's thread pools name threads by default). I'm
wondering that should Jumi Actors provide out-of-the-box a way for
producing those unique names.

--
Esko Luontola
www.orfjackal.net

Esko Luontola

unread,
Apr 21, 2013, 1:11:27 PM4/21/13
to deakblue, jumi-tes...@googlegroups.com
How would you name the actor threads? I find that information useful in
designing the API.


For example in Jumi Test Runner I would have one central thread called
"Coordinator". Also there would be some dynamically created components
each in their own thread, in which case the name would have a sequence
number: "Runner-1", "Runner-2" etc.

I might also find it useful to differentiate between multiple actor
containers inside the same JVM. Then the first container would have
thread names "jumi-suite-1-coordinator", "jumi-suite-1-runner-1",
"jumi-suite-1-runner-2" etc. and the second container would have names
"jumi-suite-2-coordinator", "jumi-suite-2-runner-1" and so on.

One idea for an API would be
`startActorThread("jumi-suite-{pool}-runner-{thread}")` which where the
{pool} and {thread} placeholders will be replaced with the automatically
generated sequence numbers. A fixed name can be produced by just not
having those placeholders in the parameter. Also, the {thread} sequence
number would be unique to each name pattern; the same container can
produce thread names "foo-1", "foo-2" etc. and "bar-1", "bar-2" etc.
independently of each other.


I should have time to work on Jumi this summer. In the meanwhile you can
use a workaround such as this to set the thread names:

import java.util.concurrent.ThreadFactory;

public class CustomNameThreadFactory implements ThreadFactory {

private final ThreadLocal<String> nextThreadName = new ThreadLocal<>();

@Override
public Thread newThread(Runnable r) {
String name = nextThreadName.get();
nextThreadName.remove(); // prevent accidentally creating two
threads with the same name
return new Thread(r, name);
}

public void setNextThreadName(String name) {
this.nextThreadName.set(name);
}
}

Which can be used like this:

CustomNameThreadFactory threadFactory = new CustomNameThreadFactory();
ExecutorService executor = Executors.newCachedThreadPool(threadFactory);
MultiThreadedActors actors = new MultiThreadedActors(executor, ...);

threadFactory.setNextThreadName("foo");
ActorThread fooThread = actors.startActorThread();

threadFactory.setNextThreadName("bar");
ActorThread barThread = actors.startActorThread();





deakblue wrote on 21.4.2013 4:48:
> Specifically, I'm interested in naming my actor threads because my
> threads are long-lived and I'm using Logback and I like the pretty
> thread names in the log :) But since you asked, I'll elaborate on some
> of the ways I'm using Jumi Actors:
>
> The way I tend to use Jumi now is to create a protective coating around
> my POJOs so that any mutable state is protected from concurrent
> read/writes OR as a way of queuing requests in a non-blocking way. It's
> an Android application with a lot of random asynchronous communication
> and I don't like blocking. That said, I don't think I'm using Jumi
> quite the way it was envisioned. I actually tuck the actor interface
> within my POJOs, this way it's transparent to client access.
>
> Below is the base class for a non-blocking command receiver. If I were
> to hook this to a firehose of inbound requests, I am assured that the
> requests will queue within a particular Command (or group of related
> commands if I shared the ActorThread) and complete in order. The client
> code, the command dispatcher (not shown), is unaware that it's an actor,
> it just gets a very fast response. On the other hand, if I wanted to
> actually complete a method call with blocking code because I was
> interested in a computed result, I could skip the Actor and provide a
> Synchronous Command. Again, the client code is unaware.
>
> package com.xxxx.consistencyservice.commands;
>
> import com.xxxx.consistencyservice.ServiceThread;
>
> import fi.jumi.actors.ActorRef;
> import fi.jumi.actors.ActorThread;
>
> public abstract class AbstractAsynchCommand implements Command,
> SynchCommand{
>
> protected String synchResponse = "** accepted " +
> this.getClass().getSimpleName();
> protected String commandId;
> protected ActorRef<SynchCommand> actorCommandHandle;
> protected static final String TAG = ServiceThread.class.getSimpleName();
> public AbstractAsynchCommand(ActorThread thread){
> String name = this.getClass().getSimpleName();
> this.commandId = name.substring(0,name.length()-"AsynchCommand".length());
> this.actorCommandHandle = thread.bindActor(SynchCommand.class, this);
> }
> public String command(String command) {
> this.actorCommandHandle.tell().synchCommand(command);
> return this.synchResponse;
> }
>
> public String commandId() {
> return this.commandId;
> }
>
> public abstract void synchCommand(String payload);
> }
>
>
> interface SynchCommand{
> void synchCommand(String payload);
> }
>
>
> Likewise, I have another class (not included) that contains complex
> mutable state, multiple synchronized internal fields. I provide
> mutators that basically "decorate" my .tell() calls as I did above.
> This way I can safely manipulate the multiple internal fields across
> multiple mutator methods. Likewise I can provide accessors using
> callbacks. Finally, I've also used Jumi Actors to create some very nice
> Observable pattern code that can monitor for changes and then pass them
> to the observers without blocking the monitor.
>
> Going beyond this, I'm interested in Jumi Actors as the basis for a
> DataFlow Framework, but I'm way too busy right now to explore this further.
>
> Best regards,
> -db-

--
Esko Luontola
www.orfjackal.net

deakblue

unread,
Apr 21, 2013, 11:30:59 PM4/21/13
to jumi-tes...@googlegroups.com

I can definitely see your use-case for an automated thread-naming scheme for teams of actors or short lived tasks.  I would want that too, "Worker-1" "Worker-2" etc.   My case is for long lived static-ish services with fixed names.  Either way, I still favor startActorThread(). From my perspective, this is the factory method for new ActorThreads so just parameterize it.  Also, I like setting it in the ActorThread itself as well.  After looking at the internals, the way I came up with is kind of hackish without some other way of exposing the thread.  (I didn't test this, I just mocked it up in an editor, but I think it'll work).

*******************
    private class ActorThreadImpl implements ActorThread, MessageProcessor {

        public void setName(final String name){
          taskQueue.send(new Runnable(){
            public void run() {
              Thread.currentThread().setName(name);
            }
          });
        }

        //for fun? would anyone ever want to fiddle with the thread priorities?
        public void setPriority(final int priority){
          taskQueue.send(new Runnable(){
            public void run() {
              Thread.currentThread().setPriority(priority);
            }
          });
        }

***************************************
public abstract class Actors {
     public ActorThread startActorThread(String name) {
ActorThread actorThread = startActorThread()
actorThread.setName(name);
return actorThread;
}

Esko Luontola

unread,
Apr 22, 2013, 10:31:32 AM4/22/13
to jumi-tes...@googlegroups.com
On Monday, 22 April 2013 06:30:59 UTC+3, deakblue wrote:

After looking at the internals, the way I came up with is kind of hackish without some other way of exposing the thread.  (I didn't test this, I just mocked it up in an editor, but I think it'll work).

That's one way of doing it. The hack I posted earlier was made on the premise that the actors library isn't changed. If you're OK with forking jumi-actors and changing startActorThread, until I have time to create an official release, then by all means do it that way.

The API I'm planning would have `ActorThread startActorThread(String name)` as the client-facing API, so if you create something similar in your fork then migration should be quite easy. The configuration-facing API (i.e. MultiThreadedActors constructor) would replace the use of a standard Executor with an interface like this:

public interface NamedThreadExecutor {
    void execute(Runnable command, String threadName);
}

That interface would come with one or two implementations, one of which would be an adapter for using any Executor.

Esko Luontola

unread,
Apr 22, 2013, 10:41:15 AM4/22/13
to jumi-tes...@googlegroups.com
Another way of doing the change is to modify MultiThreadedActors to be as shown below (plus the obvious changes to add the name parameter to Actors.startActorThread).

    @Override
   
void startActorThread(MessageProcessor actorThread, String name) {
        executor
.execute(new BlockingActorProcessor(actorThread, name));
   
}


   
@ThreadSafe
   
private static class BlockingActorProcessor implements Runnable {
       
private final MessageProcessor actorThread;
       
private final String name;


       
public BlockingActorProcessor(MessageProcessor actorThread, String name) {
           
this.actorThread = actorThread;
           
this.name = name;
       
}


       
@Override
       
public void run() {
           
Thread t = Thread.currentThread();
           
String originalName = t.getName();
            t
.setName(name);
           
try {
               
while (!Thread.interrupted()) {
                    actorThread
.processNextMessage();
               
}
           
} catch (InterruptedException e) {
               
// actor was told to exit
           
} finally {
                t
.setName(originalName);
           
}
       
}
   
}


deakblue

unread,
Apr 22, 2013, 9:53:17 PM4/22/13
to jumi-tes...@googlegroups.com
Actually, after all this, I think I might use your ThreadFactory approach PLUS my own static factory method for ActorThread creation PLUS an ActorThread decorator which exposes the thread.

Why?  Well, I actually want to share the ActorThread explicitly, as in use thread "ABC" for these X Objects and this can make my injection a little simpler.  Then I can also goof around with the naked threads if I want as well.  Also, as you point out, your approach keeps Jumi vanilla!

Stepping back for a moment, it has occurred to me that Jumi Actors is essentially a particular kind of EventBus and I wonder how it compares to other EventBus technologies like Guava, ie. it's sort of like Guava but unidirectional instead of fan out.

Anyway, thanks for all the assistance,
-Will

deakblue

unread,
Apr 23, 2013, 4:26:40 AM4/23/13
to jumi-tes...@googlegroups.com
So I used your ThreadFactory trick and this is what I can now do...

Within the Constructor of my UDP broadcast monitor, I have this now:
this.asynchHandle = ActorFactory.thread("ping-monitor-" + port).bindActor(AsynchUpdate.class, this);

The thread() method will pluck the actor thread I want by name, so I can manage re-use a bit better.  Also, the thread method actually returns this:
static class ActorWithThread extends Thread implements ActorThread{
 
private ActorThread actorThread;
private ActorWithThread(Runnable r, String name) {
super(r, name);
}

private ActorWithThread(Runnable r) {
super(r);
}
public <T> ActorRef<T> bindActor(Class<T> type, T target) {
return actorThread.bindActor(type, target);
}
}

Which means I can do:
        ActorWithThread a = ActorFactory.thread("test-thread-a");
        System.out.println("a thread: " + a.getName()); // prints "test-thread-a"
        System.out.println("priority: " + a.getPriority()); //prints "5"
        ActorWithThread a2 = ActorFactory.thread("test-thread-a");
        System.out.println("a thread =? a2 thread " + (a==a2));  //true, so now I can share injected threads by name


And now my Logback logs look like this:
03:37:12,617 c.h.c.Service(20266): TRACE [ping-monitor-29100] ...

Which is what started this in the first place.  And I get all this without forking Jumi Actors, so thanks again for the ThreadFactory idea!

Best regards,
-db-

Esko Luontola

unread,
Apr 28, 2013, 12:47:20 PM4/28/13
to jumi-tes...@googlegroups.com
deakblue wrote on 23.4.2013 4:53:
> Stepping back for a moment, it has occurred to me that Jumi Actors is
> essentially a particular kind of EventBus and I wonder how it compares
> to other EventBus technologies like Guava, ie. it's sort of like Guava
> but unidirectional instead of fan out.

I haven't used Guava's EventBus, so I only know what I've learned by
reading its documentation and source code.

Jumi Actors:
- based on an actor model
- exactly one receiver per message
- the receiver is always the same (per ActorRef)
- the focus is on to whom the message is sent
- processes events in the receiver's thread

Guava EventBus:
- based on a publish-subscribe model
- zero to many receivers per message
- the receiver(s) can be changed dynamically
- the focus is on what type of message is sent
- processes events in the sender's thread

--
Esko Luontola
www.orfjackal.net

deakblue

unread,
Apr 29, 2013, 9:17:55 PM4/29/13
to jumi-tes...@googlegroups.com
Indeed, and sorry if I distracted you too much.

Guava's Event bus is a reification of the Observer Pattern (ala pub sub), it's definitely not an Actor solution.  On the other hand, I think the delivery pattern is the crucial difference and It just made me wonder if they are maybe both special cases of a larger messaging idiom.

Thanks for the discussion,
-db-


Reply all
Reply to author
Forward
0 new messages