hobbit-project / platform

HOBBIT benchmarking platform
GNU General Public License v2.0
23 stars 9 forks source link

Abstract RabbitMQ away #117

Open Aklakan opened 7 years ago

Aklakan commented 7 years ago

Its 2017, we are 2 days away from the Java 9 release which features Flows (aka reactive streams), whereas other frameworks such as RxJava have been around for quite a while - and here we are requiring developers to invent and implement their own binary communication protocols and doing synchronization with semaphores.

There is nothing wrong with AMQP and byte channels, and its a way to achieve interoperability between heterogeneous systems. And its good that the platform has these use cases in mind. However, this technology should be there to ease complex tasks, not to make simple ones complex. Hence, a benchmark implementer should not be forced to fiddle on that level unless this is what he/she wants.

The essence of this issue is, that the platform already attempts to abstract away some complexity of the RabbitMQ channels with the Abstract*Component classes, such as with receiveCommand(), sendDataToTaskGenerator() or createContainer().

In regard to receiveCommand(): Callbacks and semaphores quickly get unmaintainable in complex systems. The primary reason is, that a callback is not an object that can be passed around where clients can subscribe to in order to encapsulate processing. For this reason, high level concepts such as Flows and CompletableFutures (aka Promises) were invented.

In regard to sendDataToTaskGenerator and createContainer, these should be abstracted with dependency injection, as in this concrete example, it would enable one to

class MyBenchmarkController {
  // The native RabbitMQ channel which backs any further abstraction
  @Resource("name=bc2tgRabbitMQ")
  protected Channel toTaskGenerator_A;

  // Java7 nio channels backed by RabbitMQ 
  @Resource("name=bc2tgJava7NIO")
  protected WriteableByteChannel toTaskGenerator_B;

  // Java 9 Flow backed by the RabbitMQ channel; gets rid of callback methods
  @Resource("name=commandQueue")
  protected Publisher<String> commandQueue;

  @Autowire
  protected DockerServiceFactory dockerServiceFactory;

  void init() {
    // Guava services: See https://github.com/google/guava/wiki/ServiceExplained
    Service dockerContainer = dockerServiceFactory.create(imageName);
    dockerContainer.start();
    ...
    dockerContainer.stop();

   commandQueue.subscribe(...);
  }
}
denkv commented 5 years ago

More ideas on possible abstractions: https://github.com/hobbit-project/platform/wiki/Work-in-Progress:-How-to-write-reusable-components-that-work-both-locally-and-on-the-platform (mentioning there so they won't be totally lost).