Wednesday, July 26, 2023

Rabbit Message Queue and Redis

 In this article I will try to give some overview about why and when to use Rabbit Message Queue and Redis cache. Starting with Redis cache

Redis cache -

  • Mainly used for caching as call time to server ( say database server ) can delay. Using redis cache saves this time, as it is the cache of the database itself.
    • Whenever a database write has happened, a worker class can update the cache to be in sync with the database.
  • Key value pair type of database supporting strings, int, lists, hash as values.
  • The list can used as stacks or queues and other data structures as well like linked list,  circular queue and all.
  • Remember, the key has to be in lower case.
  • Redis say instead of sending many continuous updates in subsequent calls, these can be piped and send as a single call.
  • Calls can be direct or pub - sub type
  • StackExchange.Redis is a popular nuget package to perform almost all the database operations in the redis documentation.
  • redis - cli can be used locally to connect to the database and perform CRUD operations.
  • Convenience of using regex in calls to retrieve data fastly.

 

Rabbit Message Queue ( RMQ ) -

  • Queue or many queues behind an exchange.
  • The exchange does the routing to the particular queue based on the header information.
  • Data in a queue can be set to be durable, meaning data is not lost after RMQ is re started. For docker containers make sure to use common volumes across container restart(s).
  • Data in a durable queue can stay from two to three days.
  • MassTransit is one nuget package which can be used with different types of Enterprise service bus like RMQ, Azure queue, AWS queue, in memory queue and all without needing to write the adapters for each.
  • When a message is sent to a RMQ it first goes to the exchange and the exchange routes that message to its queue.
  • Used mainly for mass data transfers and Mass transit client consumes it almost in no time.
  • The main reason to use Enterprise service bus is to ensure reliability of the message sent. The recipient server may be busy with some operation(s) unable to provide cycles or bandwidth to consume the incoming messages from the client. These messages can be lost if not addressed in a timely manner, thereby giving poor experience to its caller.
  • Supports direct messaging to the recipient or publish subscriber mechanism where the Consumer is listening to the queue(s) in the RMQ for any new messages.

 

Writing Consumer in Mass transit should be as straight forward as implementing the `IConsumer` type and having a task named Consume with ConsumerContext parameter like below.


    public class AfceConsumer :
        IConsumer<AfceMessage>
    {

        public Task Consume(ConsumeContext context)
        {
            Console.WriteLine("Hello {name}", context.Message.Title);
            return Task.CompletedTask;
        }
    }
The above consumer will continuously consume each message one by one in almost no time when the message of type `AfceMessage` is available in the queue.
The AfceMessage can be any reference type like a class or a record or a struct.

Mass transit also has bulk message consumer to consume message in batches.

Asp .Net Configuration

 In this article I will give some tips on how one can work with configuration with ASP .Net apps. Almost all or any ASP .Net app anyway have this `Microsoft.Extensions.Configuration.IConfiguration` or simply put it as type `IConfiguration`.

There are usually one or two `json` files `appsettings.json` or or and the `appsettings.Development.json`. These contain settings for the app to use depending on the type of environment the instance is being run on. The first is for production and the later for development environment and more can de added as well.

Now let's say or `appsettings.json` is like below. Most of these config have provision for logging settings. say in production, the default might be `Information` meaning anything below that like Debug or Trace might not be logged. For development, the default might be `Debug` meaning almost all except might be `Trace` may not be logged  which deserves another article for sure.

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft.AspNetCore": "Warning"
...
...
}
},
  "SomeApp": {
    "Host": "192.168.a.l",
    "Email": "abc@comp.co",
"Location":
{
"First": "Gatsby"
}
  }

}}

In case we need to retrieve the Host address of our SomeApp, then in the class which is loaded by the ASP .Net server let's say `FirstService` class, the `IConfiguration` can be dependency injected and the app's settings retrieved like below.

 public class FirstService
{
public readonly IConfiguration _configuration;

public  FirstService(IConfiguration configuration)

{
    _configuration = configuration

 public void RunApp()

{

 Console.WriteLine("Host Config - " + _configuration["SomeApp:Host"]);

}

}

The `_configuration["SomeApp:Host"]` should give the address value which is "192.168.a.l", in this case.
The `_configuration["SomeApp:Host:Location:First"]` should give the location value and so on.

Similarly additional configurations as json files can be added to be loaded in the `Startup` or the `Program` class as well. The fetching mechanism need not be a string key, it can be
_configuration.Get<P>() to bind the configuration to type `P` and be retrieved in a more strict type way as well.


Adding newer extension method(s) to struct types C#

 In this article, I will demonstrate on how one can add additional methods to existing struct types like int, string, char, long, etc,.

This can be beneficial when the existing methods for that type is like not handful for a certain situation say like reversing a string. Some of existing method say for string type includes `.ToUpper()`, `.ToLower()`, `.Trim()` and so on.

Let us call our new method Reverse().

First we need to have `static` class for it and `static` method like below.


```

public static class AfceClass

{

    public static string Reverse(this string theStr)
{

string theStrNew;

    foreach(char ch in theStr)
{

    thStrNew =+ ChangeCase(ch) ;

}

    return  thStrNew;


public static string ChangeCase(char chr)

{

    // steps to change or negate the char case
    return chr.toUpper();

}

}

```

Note, the use of the `this` keyword to the parameters which more or less makes the method chain.

Now, if you find any variables of type string, it should also have the Reverse() method as well and documentation if added in the comments for that method.

Extension method can be used of types other than struct or for user defined types as well. One aspect is the static class should not be nested in the same class where one is using it as well.

Sample using the generic type

```

public static class AfceClass

{

    public static E NewExtMethod<E, T>(this T theStr)
{

E theStrNew;

....

...

...

    return  thStrNew;

}

}

```
Now with Generics, the NewExtMethod<E, T> should populate with any types but make sure to pass the E and T types.

This can be further refined to be populated with only certain types with the `where` clause like below.

```

public static class AfceClass

{

    public static E NewExtMethod<E, T>(this T theStr) where T : long, int where E : long
{

E theStrNew;

....

...

...

    return  thStrNew;

}

}

```

Usage - One can use this to have like a common method say like add leading zeros to an int or a long and return as a string or even use as user types with much more options.

Browser background color or monitor brightness

Have you been in a situation where you are almost sitting the whole day in front of your browser and going through a document and find that ...