Skip to content
This repository has been archived by the owner on Jan 8, 2020. It is now read-only.

Design Rationales

Petter Måhlén edited this page Jan 29, 2014 · 1 revision

This page describes the rationales for some choices made when designing Trickle

Func0, 1, ... interfaces

An early version of Trickle used objects with a single method, and a predecessor to Trickle (Shopzilla's PageFlow) used annotations to identify the method to call in a node. We changed that because:

  • it allows type-safety, and
  • it is forward-compatible with lambdas, making the syntax in Java 8 nicer.

Single sink

Trickle forces you to have a single sink only. There are use cases for multiple sinks, for instance for calls you want to make asynchronously but that don't return any results you need. We decided to enforce single sinks in order to ensure that any errors in the graph execution will be reported or handled.

Fallbacks

The main reason for supporting fallbacks is that they enable graceful degradation in case of failures. So, if some end-user view is made up of data from 5 different services, and one of them fails, it's often much better to display the data from the 4 functioning services than an error page.

Predecessors and Inputs

There are two types of dependencies between nodes in trickle: the result of node A can be used as an input to node B, or you can specify that node A is a predecessor - must be completed - before node B can run. This is typically useful when coordinating parallel updates. It would be possible to solve the second case by simply passing node A's result to the Function in node B and ignoring it. We chose to introduce the predecessor case primarily to keep the functions executed in the nodes unaware of execution order concerns. That decreases coupling and increases reuse potential, and also makes the code cleaner.

Never use Futures as inputs to application code

A problem with raw Futures is how to get the value out of them. The easiest way is to simply to a get() on the future - and of course, if that is done before the future is complete, that'll reduce parallelism and introduce a performance bottleneck. In Trickle, while application code almost always returns Futures, it will only be called with plain values. That means that application programmers don't need to worry about interrupting the concurrent flow, and also makes testing individual functions easier.