Queue Behavior and Usage in Cache
Note
This feature is only available in NCache Enterprise Edition.
A queue in NCache is an ordered data type of first-in first-out behavior. Queues can be used to maintain information being processed at run time. For example, the application IDs of potential candidates for an organization can be stored in a queue. As it is in FIFO nature, the first candidate to apply will be interviewed first and so on.
NCache further enhances this queue by providing NCache specific features such as expiration, dependency, groups and more to the queue. In this scenario, the organization can specify a group against the queue which applied for administrative jobs.
Behavior
- A queue can be of any primitive type or custom object.
- A queue of CacheItems and nested queues are not supported yet.
- Null is not a supported value type.
- Duplicate values are supported.
- Queues are named; you need to provide a unique cache key for each queue.
Pre-requisites
- Include the following namespaces in your application:
Alachisoft.NCache.Client
Alachisoft.NCache.Client.DataTypes
Alachisoft.NCache.Client.DataTypes.Collections
Alachisoft.NCache.Runtime.Events
Alachisoft.NCache.Runtime.Exceptions
- The application must be connected to cache before performing the operation.
- Cache must be running.
- To ensure the operation is fail safe, it is recommended to handle any potential exceptions within your application, as explained in Handling Failures.
Create Queue and Add Data
The following code sample shows how a queue of Candidate type can be created using CreateQueue in cache against the cache key "CandidateQueue" without any additional parameters. It is populated using Enqueue. Using Contains, the queue is searched a specific candidate.
Tip
You can also configure searchable attributes such as groups/tags/named tags and invalidation attributes such as expiration/eviction/dependency while creating a data type.
try
{
// Pre-condition: Cache must be connected
// Specify unique cache key for queue
string key = "CandidateQueue";
// Create Queue of Candidate type
IDistributedQueue<Candidate> queue =
cache.DataTypeManager.CreateQueue<Candidate>(key);
// Check if the queue exists in cache using cache.Contains()
Candidate[] candidates = FetchCandidates();
foreach(var candidate in candidates)
{
// Add candidates to queue
queue.Enqueue(candidate);
}
// Check if a candidate exists against given ID
Candidate cand = GetCandidateByID(1002);
if (queue.Contains(cand))
{
// Candidate exists with this ID
}
}
catch (OperationFailedException ex)
{
// NCache specific exception
if(ex.ErrorCode == NCacheErrorCodes.KEY_ALREADY_EXISTS)
{
// The specified key already exists in cache,
// Either remove the existing object from cache
// Or specify another key
}
else if (ex.ErrorCode == NCacheErrorCodes.CACHEITEM_IN_DATA_STRUCTURES)
{
// Data structures cannot be of CacheItem type
// CacheItems cannot be added in data structures
}
else
{
// NCache specific exception
// Exception can occur due to:
// Connection Failures
// Operation Timeout
// Operation performed during state transfer
}
}
catch (Exception ex)
{
// Any generic exception like ArgumentNullException or ArgumentException
}
Recommendation: To ensure the operation is fail safe, it is recommended to handle any potential exceptions within your application, as explained in Handling Failures.
Fetch Queue from Cache
You can fetch a queue from cache using GetQueue, which takes a cache key as parameter. This key is the name of the queue which is specified during queue creation.
Warning
If the item being fetched is not of Queue type, a Type mismatch
exception is thrown.
try
{
// Pre-condition: Cache is already connected
// Queue with this key already exists in cache
string key = "CandidateQueue";
// Get queue and show items of queue
IDistributedQueue<Candidate> retrievedQueue = cache.DataTypeManager.GetQueue<Candidate>(key);
if (retrievedQueue != null)
{
foreach (var item in retrievedQueue)
{
// Perform operations
}
}
else
{
// Queue does not exist
}
}
catch (OperationFailedException ex)
{
// NCache specific exception
if (ex.ErrorCode == NCacheErrorCodes.NOT_A_QUEUE)
{
// Item being fetched is not of Queue type;
// Cache key corresponds to an item of different data type
}
else
{
// NCache specific exception
// Exception can occur due to:
// Connection Failures
// Operation Timeout
// Operation performed during state transfer
}
}
catch (Exception ex)
{
// Any generic exception like ArgumentNullException or ArgumentException
}
Recommendation: To ensure the operation is fail safe, it is recommended to handle any potential exceptions within your application, as explained in Handling Failures.
Remove Items from Queue
Items can be removed from a queue in FIFO manner, meaning the first item of a queue will be dequeued. The following code sample removes the first candidate from the queue as the candidate's application is processed, using Dequeue.
Tip
To remove the whole queue from cache, refer to the Remove Data Structures From Cache page.
try
{
// Pre-condition: Cache must be connected
// Queue with this key already exists in cache
string key = "CandidateQueue";
IDistributedQueue<Candidate> retrievedQueue =
cache.DataTypeManager.GetQueue<Candidate>(key);
// Remove first item of queue
retrievedQueue.Dequeue();
}
catch (OperationFailedException ex)
{
// NCache specific exception
if (ex.ErrorCode == NCacheErrorCodes.NOT_A_QUEUE)
{
// Item being fetched is not of Queue type;
// Cache key corresponds to an item of different data type
}
else
{
// NCache specific exception
// Exception can occur due to:
// Connection Failures
// Operation Timeout
// Operation performed during state transfer
}
}
catch (Exception ex)
{
// Any generic exception like ArgumentNullException or ArgumentException
}
Event Notifications on Queues
You can register cache events as well as data type events on a data type such as queue. For behavior, refer to the Feature Wise behavior topic.
The following code sample registers a cache event of ItemAdded
and ItemUpdated
as well as registers an event for ItemAdded
and ItemUpdated
on the queue in cache.
Once a queue is created in cache, an ItemAdded
cache level event is fired. However, once an item is added to queue, an ItemAdded
data type event is fired, and an ItemUpdated
cache level event is fired.
Register Event on Queue Created
try
{
// Pre-condition: Cache is connected
// Unique cache key for queue
string key = "CandidateQueue";
// Create queue of Candidate type
IDistributedQueue<Candidate> queue =
cache.DataTypeManager.CreateQueue<Candidate>(key);
// Register ItemAdded, ItemUpdated, ItemRemoved events on queue created
// DataTypeNotificationCallback is callback method specified
queue.RegisterNotification(DataTypeDataNotificationCallback, EventType.ItemAdded |
EventType.ItemUpdated | EventType.ItemRemoved,
DataTypeEventDataFilter.Data);
// Perform operations
}
catch (OperationFailedException ex)
{
// NCache specific exception
// Exception can occur due to:
// Connection Failures
// Operation Timeout
// Operation performed during state transfer
}
catch (Exception ex)
{
// Any generic exception like ArgumentNullException or ArgumentException
}
Specify Callback for Event Notification
private void DataTypeDataNotificationCallback(string collectionName, DataTypeEventArg collectionEventArgs)
{
switch (collectionEventArgs.EventType)
{
case EventType.ItemAdded:
// Item has been added to the collection
break;
case EventType.ItemUpdated:
if (collectionEventArgs.CollectionItem != null)
{
// Item has been updated in the collection
// Perform operations
}
break;
case EventType.ItemRemoved:
// Item has been removed from the collection
break;
}
}
Locking Queues
Queues can be explicitly locked and unlocked to ensure data consistency. The following code sample creates a queue and locks it for a period of 10 seconds using Lock(), and then unlocks it using Unlock().
try
{
// Pre-conditions: Cache is already connected
// Queue exists with key "CandidateQueue"
// Cache Key
string key = "CandidateQueue";
// Get queue
IDistributedQueue<Candidate> queue =
cache.DataTypeManager.GetQueue<Candidate>(key);
// Add data to queue using
// queue.Enqueue(candidate);
bool isLocked = queue.Lock(TimeSpan.FromSeconds(10));
if (isLocked)
{
// Queue is successfully locked for 10 seconds
// Unless explicitly unlocked
}
else
{
// Queue is not locked because either:
// Queue is not present in the cache
// Queue is already locked
}
queue.Unlock();
}
catch (OperationFailedException ex)
{
// NCache specific exception
// Exception can occur due to:
// Connection Failures
// Operation Timeout
// Operation performed during state transfer
}
catch (Exception ex)
{
// Any other generic exception like ArgumentNullException or ArgumentException
}
Additional Resources
NCache provides sample application for Queue datatype at:
- GitHub
- Shipped with NCache: %NCHOME%\samples\dotnet\DataTypes\DistributedQueue
See Also
List Behavior and Usage in Cache
Sets Behavior and Usage in Cache
Dictionary Behavior and Usage in Cache
Using Counter in Cache
Configure Searchable Attributes
Configure Invalidation Attributes
Query on Data Structures
Remove Data Structure from Cache