Giter Club home page Giter Club logo

codit.blog.cache's Introduction

Improving performance with Redis Cache

This example code is part of a blog post on the Codit blog about improving BizTalk performance by bypassing the BizTalk MessageBox with the help of Redis cache and a WCF IOperationInvoker.You can find the blogpost here.

RedisCacheClient

The RedisCacheClient has the following NuGet Dependencies:

  • StackExchange.Redis.StrongName

  • Newtonsoft.Json

To use the RedisCacheClient you'll have to update the ConnectionString fields (these are here only for demo-purposes), we recommend to abstract these away from the client's implementation.

Write-Operations will be done to the "master", Read-Operations will be done to the "slave". We trust Redis to do the replication of this data on multi-instance environments.

More information about configuring Redis for master/slave configuration & replication can be found here.

CacheKeys

Redis is a key-value store, to ease programming against it and to avoid typos. We introduced typed cache keys this allows us to re-use cache keys without having to worry about keeping strings up-to-date.

An example of a cachekey

public class TestCacheKey : ICacheKey
{
	public TestCacheKey(string parameter)
    {
        _name = string.Format("TestCacheKey:{0}", parameter);
    }

    private readonly string _name; 
    public string Name
    {
        get
        {
            return _name;
        }
    }
}

This is how the values are stored in Redis:

Client

To write a value, create an instance of the RedisCacheClient, and as parameters pass a typed cache key, a value and an optional time-to-live.

var client = new RedisCacheClient();
var success = client.Write(new YourCacheKey("Codit"), true, TimeSpan.FromMinutes(15));

To read a value with the client, you only need to have a cacheKey

var client = new RedisCacheClient();
var cachedValue = _cacheClient.Read<bool>(new YourCacheKey("Codit"));

The return value implements the "MayBe principle", therefor you can check in advance if there was an acutal value found. This reads easier than having null check's.

if (cachedValue.IsPresent)
{
   // do something with cachedValue.Value
}

Cache operation Invoker

The IOperationInvoker is the last step before calling the actual implementation of your service, here you have the power of skipping the implementation and returning a custom message.

You can adapt the following method to have your custom decision on continuing the service call or not.

 public Task<object> InvokeOperationAsync(object instance, object[] inputs, object state)

The example code excludes retrieving the OrganisationId from the As4 Pull request, and creation of the return message. If you want to know more about As4, the Codit blog has a series As4 For Dummies

Warning: Once you read a message, the status is set to Read and cannot be read afterwards. The only solution for this is copying the message to a new message.

This method investigates the stream of the receive message, and searches for a organisationId, if a Id is found in the message, the Cache is checked. If the cache has a positive value, a new Output Message is created.

private Message GetOutputMessageForInputMessageStream(Stream messageStream)
{
    Message outputMessage = null;
    
    var organisationId = GetOrganisationId(messageStream);
    
    var cachedValue = _cacheClient.Read<bool>(new NoMessagesAvailableCacheKey(organisationId));
    
    if (cachedValue.IsPresent && cachedValue.Value)
    {
	    // Create As4 Warning Message (EmptyMessagePartitionChannel) - for demo purposes this is removed.
	    var as4MessageStream = new MemoryStream();
    }
    
    return outputMessage;
}

If no Output message is created, the current Operation is triggered to continue to the implementation.

if (outputMessage == null)
{
    var capturedOperationContext = OperationContext.Current;
    return Task<object>.Factory.StartNew(() =>
    {
        OperationContext.Current = capturedOperationContext;
        var begin = _innerInvoker.InvokeBegin(instance, inputs, null, state);
        object[] o;

        return _innerInvoker.InvokeEnd(instance, out o, begin);
    });
}

If there is a output message created, this message is returned and the service implementation is skipped.

 return Task.FromResult((object)outputMessage);

Steps to be taken to host this behavior in BizTalk:

  • GAC the signed dll.
  • Add the WCF behavior to the machine.config
  • Add the behavior to your WCF receive port.

Links

codit.blog.cache's People

Contributors

msjonathan avatar tomkerkhove avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.