This page describes an older version of the product. The latest stable version is 14.0.

Overview

The polling event container implements the IEventListenerContainer interface. Its life-cycle consists of performing polling receive operations against the space. If a receive operation succeeds (a value is returned from the receive operation), the DataEventArrived event is invoked. A polling event operation is mainly used when simulating Queue semantics, or when using the master-worker design pattern.

The examples in this page follow a certain pattern. Each code example has two tabs: Using EventListenerContainerFactory, and PollingEventListenerContainer Code Construction.

The first tab demonstrates how to create and configure a polling container using the EventListenerContainerFactory, and the second tab demonstrates how to build and configure a PollingEventListenerContainer with a constructor and setting the different properties.

Constructing the polling container that uses the SimpleListener class as the event listener, and starting it.

ISpaceProxy spaceProxy = // either create the SpaceProxy or obtain a reference to it
IEventListenerContainer<Data> eventListenerContainer = EventListenerContainerFactory.CreateContainer<Data>(spaceProxy, new SimpleListener());
eventListenerContainer.Start();
// when needed to dispose of the container
eventListenerContainer.Dispose()

ISpaceProxy spaceProxy = // either create the SpaceProxy or obtain a reference to it
PollingEventListenerContainer<Data> pollingEventListenerContainer = new PollingEventListenerContainer<Data>(spaceProxy);
pollingEventListenerContainer.Template = new Data(false);
pollingEventListenerContainer.DataEventArrived += new DelegateDataEventArrivedAdapter<Data,Data>(ProcessData).WriteBackDataEventHandler;
// when needed dispose of the container
pollingEventListenerContainer.Dispose();

The example above performs single take operations (see below), using the provided template, which can be any .NET object (in this case a Data object with its processed flag set to false). If the take operation succeeds (a value is returned), the SimpleListener.ProcessData method is invoked. The operations are performed on the supplied space proxy.

Primary/Backup

The polling event container performs receive operations only when the relevant space it is working against is in primary mode. When the space is in backup mode, no receive operations are performed. If the space moves from backup mode to primary mode, the receive operations are started.

This mostly applies when working with an embedded space directly with a cluster member. When working with a clustered space (performing operations against the whole cluster), the mode of the space is always primary.

FIFO Grouping

The FIFO Grouping designed to allow efficient processing of events with partial ordering constraints. Instead of maintaining a FIFO queue per class type, it lets you have a higher level of granularity by having FIFO queue maintained according to a specific value of a specific property. For more details see FIFO grouping.

Static Template Definition

When performing receive operations, a template is defined, creating a virtualized subset of data within the space that matches it. GigaSpaces supports templates, based on the actual domain model (with null values denoting wildcards), which are shown in the examples. GigaSpaces allows the use of SqlQuery in order to query the space, which can be easily used with the event container as the template. Here is an example of how it can be defined:

Dynamic Template Definition

When performing polling receive operations, a dynamic template can be used. A method providing a dynamic template is called before each receive operation, and can return a different object in each call.
The event template object needs to be of IQuery type, which means if you want to use an object based template you need to wrap it with the ObjectQuery wrapper.

Performs a single blocking Take operation, with the receive timeout. When used in conjunction with batch events, first tries to perform TakeMultiple. If no values are returned, performs a blocking Take operation, with the receive timeout.

ReadReceiveOperationHandler

Performs a single blocking Read operation, with the receive timeout. When used in conjunction with batch events, first tries to perform ReadMultiple. If no values are returned, performs a blocking Read operation, with the receive timeout.

ExclusiveReadReceiveOperationHandler

Performs a single Read operation, under an exclusive read lock (similar to “select for update” in databases), with the receive timeout. Exclusive read lock mimics the Take operation, without actually taking the Entry from the space. When used in conjunction with batch events, First tries to perform ReadMultiple. If no values are returned, performs a blocking Read operation, with the receive timeout.

Important

This receive operation handler must be used within a transaction.|

When using the ExclusiveReadReceiveOperationHandler, or even the ReadReceiveOperationHandler, it is important to remember that the actual event still remains in the space. If the data event is not taken from the space, or one of its properties changes in order not to match the container template, the same data event is read again.

Here is an example of how the receive operation handler can be configured with ExclusiveReadReceiveOperationHandler:

Non-Blocking Receive Handler

When working with a partitioned cluster, and configuring the polling container to work against the whole cluster, blocking operations are not allowed (when the routing index is not set in the template). The default receive operation handlers support performing the receive operation in a non-blocking manner, by sleeping between non-blocking operations. For example, the TakeReceiveOperationHandler performs a non-blocking Take operation against the space, and then sleeps for a configurable amount of time. Here is an example of how it can be configured:

The above example uses a receive timeout of 10 seconds (10000 milliseconds). The TakeReceiveOperationHandler is configured to be non-blocking, with a non-blocking factor of 10. This means that the receive handler performs 10 non-blocking takes within 10 seconds, and sleeps the rest of the time (~1 second each time).

Batch Events

Sometimes it is better to use batch events, for instance to improve network traffic. This is done by subscribing to the BatchDataEventArrived event. This event receives a batch of event data objects in one invocation.

A prime example is the TakeReceiveOperationHandler, which when BatchDataEventArrived event are used, returns an array as a result of a TakeMultiple operation . The batch size is determined by the ReceiveBatchSize configuration attribute or property, it is set similar to the above properties modifications.

Here is an example of batch notifications using ReadReceiveOperationHandler:

Trigger Receive Operation

When configuring the polling event container to perform its receive operation, and event actions under a transaction, a transaction is started and committed for each unsuccessful receive operation, which results in a higher load on the space. The polling event container allows pluggable logic to be used in order to decide if the actual receive operation should be performed or not. This logic, called the trigger receive operation, is performed outside the receive transaction boundaries. The following interface is provided for custom implementation of this logic:

public interface ITriggerOperationHandler<TData>
{
/// <summary>
/// Allows you to perform a trigger receive operation, which controls if the active receive operation
/// is performed in a polling event container. This feature is mainly used when having polling event
/// operations with transactions where the trigger receive operation is performed outside of a
/// transaction thus reducing the creation of transactions did not perform the actual receive
/// operation.
///
/// If this method returns a non null value, it means
/// that the receive operation should take place. If it returns a null value, no receive operation is
/// attempted, thus no transaction is created.
/// </summary>
/// <param name="template">The template for the receive operation.</param>
/// <param name="proxy">The proxy to execute the operation on.</param>
/// <param name="receiveTimeout">Operation's receive timeout</param>
/// <returns>Null value when the receive operation should not be triggered, otherwise a non null value that can also
/// be used as the receive template if <see cref="UseTriggerAsTemplate"/> is set to true.</returns>
IQuery<TData> TriggerReceive(IQuery<TData> template, ISpaceProxy proxy, long receiveTimeout);
/// <summary>
/// Gets if the object that return from the <see cref="TriggerReceive"/> operation should be used as the
/// receive template instead of the configured template.
/// </summary>
bool UseTriggerAsTemplate { get; }
}

XAP.NET comes with a built-in implementation of this interface, called ReadTriggerOperationHandler. It performs a single blocking Read operation (using the provided receive timeout), thus “peeking” into the space for relevant event data. If the Read operation returns a value, this means that there is a higher probability that the receive operation will succeed, and the transaction won’t be started without a purpose. Here is how it can be configured:

Non-Blocking Trigger Handler

Handling Exceptions

During the life-cycle of the polling container, two types of exceptions might be thrown:

User Exception

Container Exception

The User Exception is an exception that occurs during the invocation of the user event listener. The Container Exception is an exception that occurs anywhere else during the life-cycle of the container (e.g. during the receive or trigger operation handler).

Subscribing to Container Exception Occurred Event

It is possible to be notified when a container exception occurred, by subscribing to the ContainerExceptionOccurred event, and get a reference to the exception.

Subscribing to User Exception Occurred Event

It is possible to be notified when a user exception occurred, by subscribing to the UserExceptionOccurred event. This arguments of this event contain the entire DataEventArgs of the original DataEventArrived. By default, any event that is thrown inside the event listener scope results in a transaction rollback, if the container is set to be transactional. This can be overridden if the user exception handler sets the event state to: ignored.

Default Values of Polling Container Configuration Parameters

The default values for all of the polling container properties such as min-concurrent-consumers, receive-operation-handler, receive-timeout and others can be found in the API docs. Each property has a corresponding Default const field that sets the default value of the property.