Embrace change

«The best way to predict the future is to invent it» — Alan Kay 
Filed under

tideland

 

Tideland EAS: agent concept

Yesterday I've introduced the new architecture of the Tideland EAS - formerly known as "Events and Services", now the "Erlang/OTP Application Server". One of the new concepts is the definition of agents for the control of business processes. Those agents are typical callback modules working like finite state machines. The state change is done by internal code, by the returning from services calls, or by the arguments of an external continuation after reaching a waypoint.
 
So here's one example of how to use the agent API from a view or a connector. First the agent will be started, then the reply will be handled asynchronously. Both, the agent and the reply call have a timeout. The first one defines the timespan in which the agent should complete its work, the second one is just for the reply call. 

start_agent(Args) -> 
  % my_agent is the name of the callback module.
  easagt:start(my_agent, Args, {5, hours}).

 process_agent(Aid) ->
  case easagt:reply(Aid, {5, seconds}) of
   {waypoint, foo, Info} ->
   ContinuationArgs = handle_foo(Info),
   easagt:continue(Aid, ContinuationArgs),
   process_agent(Aid);
   {waypoint, bar, Info} ->
   ContinuationArgs = handle_bar(Info),
   easagt:continue(Aid, ContinuationArgs),
   process_agent(Aid);
   {finished, error, Reason} ->
   {error, Reason};
   {finished, ok, Reply} ->
   {ok, Reply};
   {error, timeout} ->
   {error, timeout}
  end.

This is a very simplified code fragment, but it shows how a running agent can stop working when reaching a waypoint where external action - or interaction - is needed. The last shown error is the timeout of the reply call, the inner one can also be a timeout, in this case caused by the agent. If the timeouts aren't passed as integers representing milliseconds the time library of the CEL calculates them based on the tuples.
 
The control of state changes inside an agent is done through the result of the current processing.

process(foo, Args, StateData) -> 
  % Do something ...
  {next, bar, NewArgs, NewStateData}.

 process(bar, Args, StateData) ->
  % Do something else ...
  {call, [{svc_a, req_a, ArgsA}, {svc_b, req_b, ArgsB}], baz, NewStateData}.

 process(baz, ServiceCallResults, StateData) ->
  % Do something with the service call results ...
  {waypoint, baz, Info, yadda, NewStateData}.

 process(yadda, ContinuationArgs, StateData) ->
  % Do something with the continuation args ...
  {stop, ok, Result}.

It's easy to see how one or more services can be called, the processing will continue when all services replied or after an optional timeout, or the control can be passed to an external waypoint. Additionally simple service calls can directly be done inside the callback functions. 

{ok, Reply} = eassvc:call(svc_x, req_x, ArgsX, Timeout) 

This API isn't stable yet, but it shows the direction. I'll write more about it here.

Loading mentions Retweet
Filed under  //   eas   erlang   tideland  

Comments [0]

Tideland EAS redesign

It's time for a change, a deeper change. A change based on the experiences made during the development and testing of the EAS like it works today. The original idea behind the EAS has been an event-driven architecture where services subscribe to different types of events - therefore the name EAS, events and services. Additionally the platform contains a generic complex event processing. This system now works fine, only the timeout mechanism for replies and time based event processing is missing. So far so good.

 But there's still one problem. The idea has been that business process are a flow of events. Each step can raise one or more events that will be handled then. It's a simple idea, but it's hard to handle. The managing of the control flow is hard, especially when a change is needed. That's not worth it. So the idea of changing the design came up. There are still services, which handle requests asynchronously. Additionally there are agents, each one is a kind of state machine representing a business process. The third part is the complex event processing, still based on subscriptions.

Due to the experiences with the EAS the prototype for this new design will be available soon. The persistence of requests, replies, and aggregations together with the dispatching mechanism like it is implemented today supports the scalability using of large number of nodes in parallel. So the new approach can fulfill the requirements together with an easier API for the later implementation of services, business processes, and event processings.
 
One additional thing that helped a lot during the redesign has been my first usage of the Fundamental Modeling Concepts (FMC / http://www.fmc-modeling.org/). It really helps to design and document software-intensive systems in a simple, clear, and esthetic way. Beside static views like above dynamic ones are supported too. So I'll test it more.

Loading mentions Retweet
Filed under  //   eas   erlang   tideland  

Comments [0]

No new integration platform

I thought a bit about my idea for a next generation Tideland EAS and now made a decision. It is really an appealing idea building a new integration platform for event-driven solutions based on technologies like JSON, HTTP, and JavaScript for the service subscription. But that's not my goal. I've got real applications in mind, currently three different ones. And the EAS is just intended to be the backend framework which allows to implement them as event-driven solutions which work reliable in a 24/7 environment. So I'll continue the development as planed. Additionally I've started writing a small article about my motivation for event-driven architectures on http://www.tideland.biz which will be published soon.

Loading mentions Retweet
Filed under  //   development   erlang   tideland  

Comments [0]

Tideland EAS next generation idea

When I started the development of the Tideland EAS I had a small pure Erlang event-driven architecture in, just as the middleware for my apps. But sometimes ideas assume in an independent existence. OK, the old concept would also benefit from the reliability and scalability of Erlang/OTP, but not as much as it is in the possibilities of this platform.
 
So, while reading about and evaluating CouchDB, my concept changes. I'm currently thinking about reimplementing it as a real middleware for event-driven architectures. This draft gives a better insight:

The black steps (1) to (3) show the subscription process where a service provider sends a JavaScript filtering the subscribed events. The EAS will store some administrative data, like the ID of the subscription and the service provider, and sends the JavaScript to CouchDB as the database server. CouchDB uses the script to create a view for the subscription.
 
The red steps (1) to (6) show the event processing. A raised event sent to the EAS will be stored inside the CouchDB event table and will so also be visible in all matching views. In case of a polling service the new events will be retrieved and sent to the service. It now can process the event and send the reply or new continuing events back to the EAS. Finally - if wanted by the event source - a reply will be sent back.
 
There are still several open aspects I've got to think about. But I think it looks promising. I'll test the concept with a quick prototype.

Loading mentions Retweet
Filed under  //   development   erlang   tideland  

Comments [2]

Approaching beta step by step

During the last days I've had to stop my development on the Tideland EAS due to the migration of my root server to two new ones. Now my own projects as well as my customers do have a better environment.
 
But after that I've been able to continue the work on my small event-driven middleware for Erlang based solutions. The completion of a test business process helped to make the API for service developers more simple and consistent. Additionally the configuration and the error handling have been improved. Now there's only the configuration - and usage - of functions for the preprocessing of events and postprocessing the results is missing for a beta release. They are intended to allow the transformation of data from one format into another if e.g. two service interfaces doesn't fit.
 
After this extension the functional part for release 1.0.0 is complete. But I still have to add some functionality for reliability and scalability. So the dispatcher shall notify others if a service registers or unregisters. And in case of a restart through the supervisor they shall retrieve the registered services from other nodes. The same is needed for the configuration. So still some work to do, but that's exactly Erlangs playground. *smile*

Loading mentions Retweet
Filed under  //   development   erlang   tideland  

Comments [0]

KISS and YAGNI ignored

Even after more than 25 years of software development I sometimes forget some of the best practices. This time the principles KISS and YAGNI during the development of my platform for EDA, the Tideland Events and Services. I discovered it during the development of test services and test cases. Due to the adding of a too high flexibility the API got unhandy. So I started to change it and discovered that the internal architecture tries to cover by far too much cases - independent of their likeliness.
 
So now it's time for a larger refactoring with the goal to strip everything down to the original intention. Beside the fact that the API and the usage will get easier the code will also decrease. That's a good result for the future maintainability.

Loading mentions Retweet
Filed under  //   erlang   tideland  

Comments [0]

On OOP, COP and the Tideland EAS

My current software project is the Tideland EAS (Events and Services) as an Erlang/OTP based platfrom for my future server-side applications. To understand the design motivation behind the EAS it may be useful to get a little insight into my software development experiences.

I'm now doing software development since about 25 years, the last 20 years the object-oriented way. So my development style is mostly characterized by my personal understanding of OOP. The bundling of attributes and behaviour is a natural way of thinking and easy to understand unless the imperative way of programming isn't etched on the memory too hard. Depending on the experience of the developer it's more or less simple to determine the right candidates for pure helper classes, for those building the foundation for the own system, and those representing the business model of an application. A large number of design patterns helps to find solutions based on a common understanding.

One of the most important parts of object-orientation is the idea of message passing between instances. When developing Smalltalk Alan Kay has been heavily inspired by Carl Hewitt's research on the actor system for massively parallel, distributed, computer systems. Unfortunately instances in languages like Smalltalk, Java, or C# aren't massively parallel. So messages sent to an instance block the caller until the work is finished. *sigh*

Think about a restaurant, where the guests have to wait for their waiter who is then waiting for the cook. The cook is then cooking the meal, one part after the other, hands it out to the waiter who is then handing it out to the guests. During this the waiter can't attend on other guests. So the restaurant would need a pool of waiters to handle every guest parallely. But additionally it would also need enough cooks to serve all orders.

To allow an environment where at least such a concurrency with pools is possible the traditional environments use threads. While those are relative lightweight from the operating systems point of view they are still very heavy on the instuction level. Sadly threads are not native for objects, they are orthogonal, a kind of meta level. So instances can talk to other instances in different threads without any problem while they are working on another task. Semaphores and synchronized blocks shall help here, but the more complex a system gets and the more a development team size grows the easier it is to confuse the system, to let it get more unstable. No good basis for reliable systems. Here I'm thinking about our waiter from the example above. Guests and cooks are calling for him while he is trying to satisfy all in parallel. It's easy to imagine how fast this poor guy gets confused.

Here I come to the concurrency oriented programming, actor systems, and Erlang. While in traditional OOP languages the default behaviour is synchronous and asynchronicity has to be added manually or through special frameworks it's different in Erlang. Function calls are also snchronous, but the exchange of messages between concurrent running processes is asynchronous. Blocking calls can be simulated through an immediate waiting for the reply sent back from the process. The OTP provides functions for this inside the standard modules. Looked at that way COP seems to be very close to the original idea of OOP. In case of Erlang this gets combined with its functional paradigm, transparent distributed environments, immutable variables, no shared data, pattern matching, guards, and the integrated database Mnesia. And even if the syntax seems to be weird for the curly braced fraction it's due to the Prolog roots more clean than the actual Java or C# standards - even though Smalltalk and Scheme are still more elegant and compelling. *smile*

Those very positive characteristics made me chosing Erlang as the base for my own development. But I want a bit more than the standard OTP provides, the reason for me to develope the EAS. The name Events and Services already unveils the idea of services implementing the functionality of business domains and communication between them in the form of events. So internally the EAS is a publish/subscribe architecture. The services subscribe to topics on channels and front ends, adapters, and services publish their business events together with a topic on a channel. Some events will be handled totally by one subscriber, others will be a flow of events, serial and parallel, between multiple services. Even typical calls will be just a flow of events. The initial event may be new_customer together with the customer data, the answering event could be customer_added together with the processed data. The publisher of this event may also be a different service than the initial receiver of the first event.

The first benefit of this approach is an extreme loose coupling - good for maintenance, very good for extensibility, and even better for scalability. But there's also a second aspect that's driving my design. Typically only one class or component is receiving a request, publish/subscribe architectures allow multiple receivers, so does the EAS. First this is interesting for automatic concurrent activities. E.g. each time a contract gets cancelled the system parallely updates the customer file, tells the financial accounting to strike a balance, and notifis the customer about the receiving of the cancellation. Or inside an order process the event order_ready_for_fulfilment could start the shipping and the generating of the invoice which do their work independently. But by far more interesting is the Complex Event Processing (CEP) with different types of analysis. Events may be checked that they always occur in pairs, with a specified rate inside a time span or a time period, their order is in a specified sequence, they happen in combination, or they are matching specific conditional expressions. Based on rules those conditions may be associated and correlated in domains, their evaluation leads to the generation of new events for an automatic reaction, alerts may be rised early due to detected signs of risks, it leads to a non-technical monitoring of the environment, the understanding of the dynamic nature of the business may be improved.

I've used the subjunctive here a lot, consciously, because the benefit isn't for free. First detecting the right business domains for the implementation as services and to not build a too fine granularity isn't easy. And second detecting the right correlation domains together with the optimal ruleset is a hard job and one has to think hard and long if it fits for the own situation. I'll see which experiences I'll make when the systems are up and running. But it definitely it's interesting and worth a try.

Loading mentions Retweet
Filed under  //   development   erlang   tideland  

Comments [0]

Uuaaaaaaah!

Strange sound? It's just the yawning of an awakening blog. Yes, I've got to admit that I've not even stopped to write here in my holidays. I've even forgot to start writing after my holidays ended. *sigh*

But that doesn't mean that I've stopped everything. Beside the continuing of our renovation - only the rear corridor and some smaller tasks are left - I've continued my development and started the preparing a conference session. And both are about very similar topics. I'm now working with distributed solutions since many years, but mostly typical N-tier applications with horizontal scaling using multiple web or application servers, EAI, or SOA. Now my focus switches to concurrent distributed solutions and EDA.

Today we more and more get networked using system with more and more processors or cores. IT systems are woven into our work and into our private life. So while in earlier times it has been enough to write an application which behaves almost autistic and concentrates on doing things one after each other developers today have to handle more complex scenarios. Their systems have to be able to parallelize work to use the new infrastructure, react on different kinds of stimmulations and events, analyze them if they are related, and process them the regular way as well as perform autonomous actions based on the analyze results. The typical flow inside an application is changing and gets more and more natural.

While this may lead to extreme powerful solutions the developer needs an infrastructure to develope and operate them. Especially the dynamic behaviour resulting out of the event evaluation is hard to control and even harder to debug. So my Tideland Events and Services tries to provide an infrastructure for event-driven applications based on Erlang. It contains - or will contain -

  • services for the processing of events,
  • channels for the distribution of events to subscribed services,
  • aspects for the pre and post processing of events,
  • automatic service and channel discovery in a network of nodes,
  • restoring of service states in case of a service restart, and
  • contexts as an environment for related events.
Additionally I'll add internal and remote monitoring features and adapters for the integration of external clients. Alltogether the EAS surely will be no middleware for a real EDA, but a small platform for event-driven Erlang applicationswell integrated into the OTP.

Loading mentions Retweet
Filed under  //   development   erlang   tideland  

Comments [0]

Erlang development progress

After a short break - I've finished my article about Erlang for the German iX magazine - my Erlang development continued. I've spent most of my time into the improvement of the Tidleland CEL Lightweight Message Bus (CELLMB) which is now working really smooth. First approaches have been too complex but now it's simple and fast. I've don't really implemented a bus, Erlang already has a very good communication infrastructure. So I only use this. The major component is a supervisor managing and monitoring the services. Those are locally registered processes based on gen_server and with own service-depending callbacks. So e.g. the statement

{ok, Reply} = cellmb:request(Ctx, configuration, read, {my_app, my_group, path, to, my, var})

leads to the call of

my_cfg:read(Ctx, {my_app, my_group, path, to, my, var}, State).

Management and lifecycle are implemented in cellmb and cellmbsvc, so the writing and usage of own services is really simple. The next advantage is the semi-automatic distribution of messages. So imagine the following situation: due to a mix of load-balancing, a higher availability through redundancy, and the access of local resources the node alpha provides the services one and two, the node beta the services two and three, the node gamma the services three and four, and the node delta the services four and one. Each service is located on two nodes but each node doesn't provide all services. In other configurations there also may be a different distribution of services, e.g. non-overlapping or some services on all nodes. Clients of the CELLMB don't have to care. So if a client on node alpha publishes the message

{ok, Reply} = cellmb:request(Ctx, three, do_something, Args)

the system will discover which node provides service three - here the nodes beta and gamma - and establishes a proxy service to one of them. The message will then be resend through the proxy, like all following messages. If a connection is broken during the operation the system tries to establish a new one or - in case of a failure - throw an exception. So there are still some features missing, like a simple SOAP client interface, the migration of services between nodes during runtime, and pro- and post-processing of messages matching a defined pattern. The latter is intended for a kind of aspects. I'll add those features later when - or if - I need them.

Currently I'm implementing the first common services. The status will be documented in our wiki. Most of the standard implementations will use Mnesia for the persistency. My first trials have been really promising.

Loading mentions Retweet
Filed under  //   development   erlang   tideland  

Comments [0]

Exciting days

The current days are a bit exciting with only few spare time for me. It started last Friday with a quick flight to Poland and the birthday party of my brother in law in the evening. On Sunday we celebrated the confirmation of our niece. Then from Monday till Thursday I got two courses in software architecture by the CMU SEI - Software Architecture: Principles and Practices (SAPP) and Documenting Software Architectures (DSA). On Monday and Tuesday Software Product Lines (SPL) and in May Software Architecture Design and Analysis (SADA) will follow. Last Tuesday I finished the work on my Erlang article which will be published next month. Today our little daughter Vanessa has her 12th birthday and on Sunday our older daughter Janina has her confirmation. *phew*

But I also had the chance to start the next improvement on the Tideland CEL Lightweight Message Bus. I'm currently adding a registry for the dynamic resolution of service names in a set of networked nodes. So if a publish can't be addressed to a local service the broker will retrieve a reference to an instance from the other nodes and cache this information. In the next step I'll add some kind of aspect orientation. So functions for cross-cutting concerns can be assigned to services so that they are executed before, after or around a service function.

My postings on COP and OOP led to much interest and response. Some of the comments in other forums showed that the writer doesn't know Erlang at all. In their eyes functional and object-orientation are diametrically opposed. So how about CLOS? Hmmm. But others could follow. So I'll write a small introduction Erlang for the OO-minded.

Loading mentions Retweet
Filed under  //   development   tideland  

Comments [0]