Terraform – Provisioning an Azure App Service

In my previous post on Getting started with Terraform I covered a very quick, and vague explanation of what Terraform is, and what it does. In this post, I’m going to cover the explanation of what the various syntax looks like; I’m also going to provision some infrastructure in the form of an App Service.

Before we get into the what we’ll need to create an app service, let’s first analyse the config that we used in the previous post:

# Configure the Azure provider
terraform {
  required_providers {
    azurerm = {
      source = "hashicorp/azurerm"
      version = ">= 2.26"
    }
  }
}

provider "azurerm" {
  features {}
}

resource "azurerm_resource_group" "rg" {
  name     = "myTFResourceGroup"
  location = "ukwest"
}

Let’s breakdown exactly what we’re seeing here for the resource:

Now that we’ve broken that down, it makes sense that, if we want to deploy an App Service, that we simply need to know what the correct type of the app service is. There’s probably a list of these somewhere.

Let’s have a look at the config for the App Service:

# App Service
resource "azurerm_app_service_plan" "app-service-plan" {
  name                = "pcm-app-service-plan"
  location            = azurerm_resource_group.rg.location
  resource_group_name = azurerm_resource_group.rg.name
  sku {
    tier = "Standard"
    size = "S1"
  }
}
resource "azurerm_app_service" "app-service" {
  name                = "pcm-app-service"
  location            = azurerm_resource_group.rg.location
  resource_group_name = azurerm_resource_group.rg.name
  app_service_plan_id = azurerm_app_service_plan.app-service-plan.id
}

Again, let’s break this down – starting with the plan:

Finally, let’s have a look at the app service itself – there’s not too much difference here:

If we now run

terraform.exe plan

Then we’ll see that it intends to create an app service plan and app service within that plan; running:

terraform.exe apply

Will execute that and generate our new resources.

Terraform – Getting Started

In this post, I’m going to download Terraform and create a resource group, and then change the location of that resource group. Most of what is in this post is much more succinctly put in the link to the Terraform tutorial at the end. Feel free to jump to the end and go there (I won’t be offended).

Download

Terraform is an application that runs locally, however, the install procedure is essentially just download an exe and place it in a directory. The download link is here. For my test, I downloaded the 64 bit Windows exe, and just extracted it to c:\tmp.

If you now run the Windows Terminal, you can run the terraform.exe and you’ll see a list of possible commands:

Since this is just an experiment, I won’t edit the path (perhaps we’ll come back to that in a later post), but if you are installing this, then it makes sense to have it in your Windows PATH – that way you can run it from anywhere.

To set-up terraform, the first step is to run:

.\terraform.exe init

If you do that now, you’ll get an error:

The directory has no Terraform configuration files. You may begin working
with Terraform immediately by creating Terraform configuration files.

Configuration Files

Configuration files essentially tell Terraform what you want it to do. At a very basic level, they have two sections:

Provider Block – where are we creating infrastructure

Resource Block – what are we creating

There are other features and sections, but getting down to basics, we need to say what we are creating, and where to create it.

The sample configuration from the tutorial referenced at the bottom of this post is this:

terraform {
  required_providers {
    azurerm = {
      source = "hashicorp/azurerm"
      version = ">= 2.26"
    }
  }
}

# Provider - creating Infrastructure in Azure
provider "azurerm" {
  features {}
}

# Resource - creating a resource group
resource "azurerm_resource_group" "rg" {
  name     = "myTFResourceGroup"
  location = "westus2"
}

Now that we’ve created that, we can run init again; this time, it should work:

.\terraform.exe init

Plan

Let’s run this. Step one is to log-in to Azure – to do this, you’ll need the Azure CLI:

az login

Once you’re logged in to Azure, create the terraform plan:

.\terraform.exe plan

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
+ create

Terraform will perform the following actions:

+ resource “azurerm_resource_group” “rg” {
+ id = (known after apply)
+ location = “westus2”
+ name = “myTFResourceGroup”
}

Plan: 1 to add, 0 to change, 0 to destroy.

That all looks good – so let’s apply that:

.\terraform.exe apply

This takes the plan, and executes it. Checking in the Azure Portal, I can see that I now have a resource group called myTFResourceGroup:

Okay, so this is where the tutorial took me to.

Change of Plan

I happen to live in the UK; so the first thing I want to try is to change the location. I actually thought that terraform would balk at this; but no. Here’s the modified .tf file:

terraform {
  required_providers {
    azurerm = {
      source = "hashicorp/azurerm"
      version = ">= 2.26"
    }
  }
}

provider "azurerm" {
  features {}
}

resource "azurerm_resource_group" "rg" {
  name     = "myTFResourceGroup"
  location = "ukwest"
}

When I run this, it actually comes up with a way to get from where it is to where I want it to be:

PS C:\tmp> .\terraform.exe plan
azurerm_resource_group.rg: Refreshing state… [id=/subscriptions/16a7fc79-9bea-4d04-83a1-09f3b260adb0/resourceGroups/myTFResourceGroup]

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
-/+ destroy and then create replacement

Terraform will perform the following actions:

# azurerm_resource_group.rg must be replaced
-/+ resource “azurerm_resource_group” “rg” {
~ id = “/subscriptions/16a7fc79-9bea-4d04-83a1-09f3b260adb0/resourceGroups/myTFResourceGroup” -> (known after apply)
~ location = “westus2” -> “ukwest” # forces replacement
name = “myTFResourceGroup”
– tags = {} -> null
}

Plan: 1 to add, 0 to change, 1 to destroy.

Okay, so what it’s telling me is that it’s going to trash my resource group, and recreate it in the correct location. That seems fine, so I’ll apply that change.

Pulling The Rug

Next, I wanted to see what would happen if I just removed the resource group from the portal. My guess was that Terraform should realise what happened and simply recreate it.

And, sure enough, that’s exactly what it did:

An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
+ create

Terraform will perform the following actions:

# azurerm_resource_group.rg will be created
+ resource “azurerm_resource_group” “rg” {
+ id = (known after apply)
+ location = “ukwest”
+ name = “myTFResourceGroup”
}

Plan: 1 to add, 0 to change, 0 to destroy.

References

https://learn.hashicorp.com/tutorials/terraform/azure-build?in=terraform/azure-get-started

Service Bus Batching and Pre-Fetch

Azure Service Bus is often used as a way to link services (as the name suggests). This typically means that the throughput is large, but not so large that anyone worries about the speed. However, in this post, I’m going to cover some techniques to speed up service bus messaging.

A quick disclaimer here, though: it might be that if you’re reading this then you’re not using the best tool for the job, and perhaps something more lightweight might be a better fit.

Essentially, there are two inbuilt methods in Service Bus to do this: Batching, and Prefetch; let’s look at Batching first.

Batching

The principle behind batching is very simple: instead of making multiple calls to Azure Service Bus with multiple messages, you make one call with all the messages that you wish to send.

Let’s see some code that sends 1000 messages:

var stopwatch = new Stopwatch();
stopwatch.Start();

var queueClient = new QueueClient(connectionString, QUEUE_NAME);

for (int i = 0; i < 1000; i++)
{
    string messageBody = $"{DateTime.Now}: {messageText} ({Guid.NewGuid()})";
    var message = new Message(Encoding.UTF8.GetBytes(messageBody));

    await queueClient.SendAsync(message);
}
await queueClient.CloseAsync();

stopwatch.Stop();
Console.WriteLine($"Send messages took {stopwatch.ElapsedMilliseconds}");

The timing for these posts is not a benchmark test, but whatever my test recorded at the time – your mileage may vary a lot, although I would say they are a fair rough estimation. As you’ll see later on, the differences are very stark.

In my tests, sending 1000 messages took around 30 seconds (which is good enough for most scenarios, as they are unlikely to be sent in a batch such as this). Let’s see how we can batch the messages to speed things up:

var stopwatch = new Stopwatch();
stopwatch.Start();

var queueClient = new QueueClient(connectionString, QUEUE_NAME);
var messages = new List<Message>();

for (int i = 0; i < 1000; i++)
{
    string messageBody = $"{DateTime.Now}: {messageText} ({Guid.NewGuid()})";
    var message = new Message(Encoding.UTF8.GetBytes(messageBody));                

    messages.Add(message);
}
await queueClient.SendAsync(messages);
await queueClient.CloseAsync();

stopwatch.Stop();
Console.WriteLine($"Send messages took {stopwatch.ElapsedMilliseconds}");

As you can see, there’s not a huge amount of change to the code. It’s worth noting that in the first example, if the code crashes half way through the send, half the messages would be sent – whereas with the batch, it’s all or nothing. However, this came in at under a second:

On the receive side, we have a similar thing.

Batch Receive

Here, we can receive messages in chunks, instead of one at a time. Again, let’s see how we might receive 1000 messages (there are multiple ways to do this):

var stopwatch = new Stopwatch();
stopwatch.Start();

var messageReceiver = new MessageReceiver(connectionString, QUEUE_NAME);
for (int i = 0; i < 1000; i++)
{
    var message = await messageReceiver.ReceiveAsync();
    string messageBody = Encoding.UTF8.GetString(message.Body);
    Console.WriteLine($"Message received: {messageBody}");

    await messageReceiver.CompleteAsync(message.SystemProperties.LockToken);
}

stopwatch.Stop();
Console.WriteLine($"Receive messages took {stopwatch.ElapsedMilliseconds}");

The execution here takes around 127 seconds (over 2 minutes) in my tests:

The same is true for batch receipt as for batch send; with a slight caveat:

var stopwatch = new Stopwatch();
stopwatch.Start();
Int count = 1000;
int remainingCount = count;

while (remainingCount > 0)
{
    var messageReceiver = new MessageReceiver(connectionString, QUEUE_NAME);
    var messages = await messageReceiver.ReceiveAsync(remainingCount);

    foreach (var message in messages)
    {
        string messageBody = Encoding.UTF8.GetString(message.Body);
        Console.WriteLine($"Message received: {messageBody}");
        remainingCount--;
    }

    await messageReceiver.CompleteAsync(messages.Select(a => a.SystemProperties.LockToken));
}

stopwatch.Stop();
Console.WriteLine($"Receive messages took {stopwatch.ElapsedMilliseconds}");
Console.WriteLine($"Remaining count: {remainingCount}");

Note that the CompleteAsync can also be called in batch.

You may be wondering here what the while loop is all about. In fact, it’s because batch receive isn’t guaranteed to return the exact number of messages that you request. However, we still brought the receive time down to around 10 seconds:

A Note on Batching and Timeouts

It’s worth bearing in mind that when you retrieve a batch of messages, you’re doing just that – retrieving them. In a PeekLock scenario, they are now locked; and, if you don’t complete or abandon them, they will time out like any other message. If you have a large number of messages, you may need to extend the timeout; for example:

var messages = await messageReceiver.ReceiveAsync(remainingCount, TimeSpan.FromSeconds(20));

In the next section, we’ll discuss the second technique, of allowing the service bus to “run ahead” and get messages before you actually request them.

Prefetch

Prefetch speeds up the retrieval of messages by getting Azure Service Bus to return messages ahead of them being needed. This presents a problem (similar to receiving in batch), which is that the system is actually retrieving messages on your behalf before you ask for them. In this example, we’ve been using PeekLock – that is, the message is left on the queue until we explicitly complete it. However, once you Peek the message, it’s locked. That means that with the code above, we can easily trip ourselves up.

int count = 1000;
var stopwatch = new Stopwatch();
stopwatch.Start();

var messageReceiver = new MessageReceiver(connectionString, QUEUE_NAME);
messageReceiver.PrefetchCount = prefetchCount;
for (int i = 0; i < count; i++)
{
    var message = await messageReceiver.ReceiveAsync(TimeSpan.FromSeconds(60));
    string messageBody = Encoding.UTF8.GetString(message.Body);
    Console.WriteLine($"Message received: {messageBody}");

    await messageReceiver.CompleteAsync(message.SystemProperties.LockToken);
}

stopwatch.Stop();
Console.WriteLine($"Receive messages took {stopwatch.ElapsedMilliseconds}");

Note the extended timeout on the Receive allows for the prefetched messages to complete.

Here’s the timing for Prefetch:

This is slightly quicker than processing the messages one at a time, but much slower than a batch. The main reason being that the complete takes the bulk of the time.

Remember that with Prefetch, if you’re using PeekLock, once you’ve pre-fetched a message, the timeout on the lock starts – this means that if you’re lock is for 5 seconds, and you’ve prefetched 500 records – you need to be sure that you’ll get around to them in time.

ReceiveAndDelete

Whilst the Prefetch messages timing out may be bad, with ReceiveAndDelete, they are taken off the queue, this means that you can consume the messages without ever actually seeing them!

Prefetch with Batch

Here, we can try to use the prefetch and batch combined:

int count = 1000
var stopwatch = new Stopwatch();
stopwatch.Start();
int remainingCount = count;

while (remainingCount > 0)
{
    var messageReceiver = new MessageReceiver(connectionString, QUEUE_NAME);
    messageReceiver.PrefetchCount = prefetchCount;
    var messages = await messageReceiver.ReceiveAsync(remainingCount);
    if (messages == null) break;

    foreach (var message in messages)
    {
        string messageBody = Encoding.UTF8.GetString(message.Body);
        Console.WriteLine($"Message received: {messageBody}");
        remainingCount--;
    }

    await messageReceiver.CompleteAsync(messages.Select(a => a.SystemProperties.LockToken));
}

stopwatch.Stop();
Console.WriteLine($"Receive messages took {stopwatch.ElapsedMilliseconds}");
Console.WriteLine($"Remaining count: {remainingCount}");

In fact, in my tests, the timing for this was around the same as a batch receipt:

There may be some advantages with much higher numbers, but generally, combining the two in this manner doesn’t seem to provide much benefit.

References

https://www.planetgeek.ch/2020/04/27/azure-service-bus-net-sdk-deep-dive-sender-side-batching/

https://markheath.net/post/speed-up-azure-service-bus-with-batching

https://github.com/Azure/azure-service-bus-dotnet/issues/441

https://markheath.net/post/migrating-to-new-servicebus-sdk

https://weblogs.asp.net/sfeldman/understanding-Azure-service-bus-prefetch

https://docs.microsoft.com/en-us/azure/service-bus-messaging/service-bus-performance-improvements?tabs=net-standard-sdk-2

https://docs.microsoft.com/en-us/azure/service-bus-messaging/service-bus-prefetch

Azure Service Bus – Auto Delete on Idle

In the past few months, I’ve written, and spoken quite a lot about Azure Service Bus – especially the new features that are now available out of the box. here I wrote about Auto-forwarding, and in this post, I’m going to cover auto-delete; I think the two subjects go hand-in-hand.

The idea behind auto-delete is that if a set of messages are time sensitive, then the message queue can be flagged for auto-deletion. This is not the same as “Time To Live” for a message, because the entire queue is deleted after a period of inactivity!

Let’s see how we can set-up a new queue, in code (see the referenced post above for the NuGet packages that you’ll need for this):

        private static async Task CreateAutoDeleteQueue(string connectionString, string queueName)
        {
            // Create authorisation rules
            var authorisationRule = new SharedAccessAuthorizationRule(
                "manage", new[] { AccessRights.Manage, AccessRights.Listen, AccessRights.Send });

            var serviceBusAdministrationClient = new ServiceBusAdministrationClient(connectionString);
          
            var options = new CreateQueueOptions(queueName)
            {
                AutoDeleteOnIdle = TimeSpan.FromMinutes(5)
            };
            options.AuthorizationRules.Add(authorisationRule);

            var queue = await serviceBusAdministrationClient.CreateQueueAsync(options);

        }

We can now post a number of messages to that queue:

Then, 5 minutes after the last message have been posted (or any activity has taken place), the queue is deleted:

References

https://www.serverless360.com/blog/hidden-gems-azure-service-bus

Service Bus Management And Auto Forwarding

In preparation for a talk I’m giving, I started looking into ways that you can create Azure Service Bus queues programatically (If you want to see some of the other posts that came out of the research for this talk, they’re here and here).

In fact, there are a few different ways, and it’s very difficult to cut through the confusion to work out which method is the new way. In this article, Microsoft recommend the method that I cover in this post.

In this post, I’ll cover creating a new message queue in code, and configuring it to auto-forward to a second queue.

The Old Way

If you go back to some of my earlier posts on Azure Service Bus, you’ll see that an object called the QueueDescription was used excessively (here and here). In the newer version of the SDK that’s no longer used, and management has been separated from the usage of the service bus. This seems to make sense, when you consider that most people using the Service Bus will not need to change the structure of it; however, there were times when having the ability to create a queue that didn’t exist would make for more resilient software.

The New Way(s)

Microsoft have replaced this with, at the time of writing, three separate alternatives. This has made the whole process very confusing – especially since some of the Microsoft documentation still talks about using QueueDescription! They, however, recommend using the Azure.Messaging.ServiceBus package.

At the time of writing, that was 7.0.1:

<PackageReference Include="Azure.Messaging.ServiceBus" Version="7.0.1" />

Creating a Queue

One of the advantages here is that you get very granular control over exactly what you’re creating; but that also means that you’re responsible for creating things such as access policies. Let’s try the following code:

var authorisationRule = new SharedAccessAuthorizationRule(
    "manage", new[] { AccessRights.Manage });

var options = new CreateQueueOptions(source);
options.AuthorizationRules.Add(authorisationRule);
            
var serviceBusAdministrationClient = new ServiceBusAdministrationClient(connectionString);
var queue = await serviceBusAdministrationClient.CreateQueueAsync(options);

In fact, this causes the following error on run:

System.ArgumentException: ‘Manage permission should also include Send and Listen’

We’re now in a world of open source, which means we can see why this doesn’t work by looking at the code. In fact, if you specify Manage privilege, it expects three permissions (that is, you must also allow Listen and Send). The working code looks like this:

var authorisationRule = new SharedAccessAuthorizationRule(
                "manage", new[] { AccessRights.Manage, AccessRights.Listen, AccessRights.Send });

var options = new CreateQueueOptions(source);
options.AuthorizationRules.Add(authorisationRule);
            
var serviceBusAdministrationClient = new ServiceBusAdministrationClient(connectionString);
var queue = await serviceBusAdministrationClient.CreateQueueAsync(options);

In fact, the reason that I started to look into queue management, was that I wanted to see if I could configure a queue with auto forwarding, without using the Azure Portal or the Service Bus Explorer.

Auto Forwarding

In fact, it’s actually quite easy. Once you start playing with the SDK, you’ll see that you can use CreateQueueOptions to specify most queue features:

var authorisationRule = new SharedAccessAuthorizationRule(
                "manage", new[] { AccessRights.Manage, AccessRights.Listen, AccessRights.Send });

var serviceBusAdministrationClient = new ServiceBusAdministrationClient(connectionString);

var optionsDest = new CreateQueueOptions(destination);
optionsDest.AuthorizationRules.Add(authorisationRule);
var queueDest = await serviceBusAdministrationClient.CreateQueueAsync(optionsDest);

var options = new CreateQueueOptions(source)
{
    ForwardTo = destination                
};
options.AuthorizationRules.Add(authorisationRule);
            
var queue = await serviceBusAdministrationClient.CreateQueueAsync(options);

Here, we’re setting up two queues (you can only forward to a queue that exists), referred to in the string variables source and destination, then we simply set the ForwardTo property of the second queue.

References

https://docs.microsoft.com/en-us/azure/service-bus-messaging/service-bus-management-libraries

https://www.serverless360.com/blog/auto-forwarding-a-hidden-gem-of-service-bus

CosmosDb – Errors on Inserting New Data

It’s been a while since I looked at CosmosDB (there is a chapter in my book – to the right of your screen – that covers some details of using CosmosDD, but using the MongoDB Api. To get going with Cosmos, you obviously need to create yourself a Cosmos resource in the Portal (or somehow). Once that’s done, you can interact with it using the package:

Microsoft.Azure.Cosmos

You need to create a client, database, and container:

var cosmosClient = new CosmosClient(endpointUri, primaryKey, options);

var database = await cosmosClient.CreateDatabaseIfNotExistsAsync(databaseId);            
var container = await database.CreateContainerIfNotExistsAsync(containerId, $"/{partition}");

You can then add to the container like this:

var response = await container.CreateItemAsync<ItemType>(newItem, new PartitionKey(partitionKey));

In this post, I wanted to cover a couple of errors that I got when trying to use it, and some possible solutions. For this post, I was using the Core (SQL) API.

You Need an ID

The first error was:

Microsoft.Azure.Cosmos.CosmosException: ‘Response status code does not indicate success: BadRequest (400); Substatus: 0; ActivityId: cdf12360b-0cbc-4575-9a1c-966f26c2351a; Reason: (Message: {“Errors”:[“The input content is invalid because the required properties – ‘id; ‘ – are missing”]}

The reason here is that, when you’re writing to the DB, you need an “ID” field; or, more specifically, an “id” field. This means that either your model should have a field names “id”, or you should reference that name in a Json Property, or you can call it “Id”, and use something like this:

var options = new CosmosClientOptions()
{
    SerializerOptions = new CosmosSerializationOptions()
    {
        PropertyNamingPolicy = CosmosPropertyNamingPolicy.CamelCase
    }
};
var cosmosClient = new CosmosClient(endpointUri, primaryKey, options);

Partition Key

The next error relates to the partition key. You typically create your container like this:

var container = await database.CreateContainerIfNotExistsAsync(containerId, $"/{partitionkey}");

And then add data to it like this:

var response = await container.CreateItemAsync<ItemType>(newItem, new PartitionKey(partitionkey));

Essentially, the rule here is this:

Whatever you specify as the partition key must exist in the payload with the exact same name.

Microsoft.Azure.Cosmos.CosmosException: ‘Response status code does not indicate success: BadRequest (400); Substatus: 1001; ActivityId: 88c1895e-a23c-5812-c205-d4503555d2cd; Reason: (Message: {“Errors”:[“PartitionKey extracted from document doesn’t match the one specified in the header”]}

You can find out what it thinks you’ve set the partition key to by using the following code:

var properties = await container.ReadContainerAsync();
Console.WriteLine(properties.PartitionKeyPath);

When I say exactly, I mean it has to be the same case in the payload; so if you’re key is Item, and you supply the field item, you’ll get this error. Such a mismatch can be caused by the camel casing that we mentioned earlier!

References

https://stackoverflow.com/questions/29725561/documentdb-replacedocument-fails

Creating a Running Game in VueJS – Part 5 – Gameplay and Graphics

In this, the fifth and final instalment of my series on creating a game using VueJS, we’re going to improve the gameplay a little, and we’re also going to replace our squares and oblongs with graphics.

If you’re new to this series, I’d encourage you to jump back to the first post.

The code for this post is here.

Gameplay and Tidy up

If you’ve played around with the game, you’ll realise there’s quite an easy way to cheat – if you simply press both keys at the same time, it behaves as though you were pressing the keys in quick succession (which, in fact, you are). Let’s stop that by adding a slight delay.

  
onKeyDown(e) {      
            if (this.lastPressed + 50 > Date.now()) {
                return;
            } else {
                this.lastPressed = Date.now();
            }

lastPressed is just added to the data properties.

Next, you may have noticed that we can run past the finish line, and the game continues after it’s finished… which actually means it’s impossible to win, because if you win, once the time gets to zero, you lose.

We can fix this pretty easily by simply stopping the timer once the game is finished; in App.vue, the update function should have the following code where we check when the player passes the finish line:

if (this.playerX > this.finishLine) {
    this.isGameFinished = true;
    this.playerWon = this.isGameFinished && (this.secondsRemaining > 0);
    clearInterval(this.interval);
}
if (this.secondsRemaining <= 0) {
    this.isGameFinished = true;
    this.playerWon = this.isGameFinished && (this.secondsRemaining > 0);
    clearInterval(this.interval);
}

this.interval is set in the init method:

init() {
    this.interval = setInterval(this.update, 10);
    this.startTime = new Date();
    this.startTime.setSeconds(this.startTime.getSeconds() + 20);
},

The next thing we need is to replace our box with some actual graphics.

Graphics

The principle behind animation (any animation, not just in a game) is that you take a series of still picture, and play them rapidly.

I couldn’t find a spritesheet of anyone running, so I created some images of my own; they look absolutely ridiculous, and are essentially made up from using the filled circle and rounded corner rectangle in paint – but then I never claimed to be any good at graphics art. Anyway, for the purpose of this, I’ve dropped them in the assets folder:

It’s a pretty good bet that you (the reader) is better at graphics art than I am, so I would strongly encourage you to not use my graphics if you’re following along. However, they’re in the GitHub repo if you wish to.

To start with, we’ll need to store the names of the images, and the last time we switched the image; so we’ll add a couple of variables to the App.vue script:

const images = [ "daley-1.png", "daley-2.png", "daley-3.png" ];
let lastSwitch = (new Date()).getTime();

We’ll also need a data property to track which image we’re displaying:

    data: function() {                    
        return {
            . . .
            currentImageIdx: 0            
        };
    },

The next step is to slightly change our GameObject such that we now display an image:

<template>
    <div v-bind:style="location">
        <img v-bind:src="image" />
    </div>
</template>
<script>
export default {
  name: 'GameObject',
  props: {
    type: String,
    location: String,
    image: String
  }
}
</script>

In App.vue we’ll need to bind that image:

<GameObject
    v-bind:location="playerLocation"
    type="player"
    v-bind:image="playerImage">
</GameObject>

And a computed property to return it:

playerImage: function() {                        
    return require("./assets/" + images[this.currentImageIdx]);
},

That’s pretty much it; all that remains is to cycle through the images. I’ve done this in the update method, and tried to make it faster as you run faster:

if (this.speed > 0) {
    const refreshSpeed = 1000 - (this.speed * 3);
    if ((new Date()).getTime() > lastSwitch + refreshSpeed) {
        this.currentImageIdx = 
            (this.currentImageIdx < images.length - 1) 
            ? this.currentImageIdx + 1 : 0;
        lastSwitch = new Date().getTime();
    }
}

It’s not perfect, but it roughly looks like he’s running faster as you move him faster.

Summary

This is going to be the last post of my very poor attempt to recreate the amazing Sprectrum game of my youth. As I said at the start, I always find this a useful way to try to learn a new front-end framework – you need to learn about how and when the screen is rendered, and how it deals with interesting things like displaying graphics, updating data, etc.

Git Bisect with Automated Tests

Some time ago, I saw a talk at DDD North about git bisect (it may well have been this one). I blogged about it here. I can honestly say that it’s one of, if not the, most useful thing I’ve ever learnt in 10 minutes!

However, the problem with it is that you, essentially, have to tell it what’s good and what’s bad. In this post, I’ll be detailing how you can write automated tests to determine this, and then link them in.

Using existing tests to determine where something broke

In this example, I’ll be using this repository (feel free to do the same). The code in the repository is broken, but it hasn’t always been, and there are some tests within the repository that clearly weren’t run before check-in, and are now broke (I know this, because I purposely broke the code – although this does happen in real life, and often with good intentions – or at least not bad).

We’re using xUnit here; but I’m confident that any test framework would do the same. The trick is the dotnet test command; from the docs on that command:

If all tests are successful, the test runner returns 0 as an exit code; otherwise if any test fails, it returns 1.

As with the previous post, we need to start with a good and bad commit; for the purpose of this post, we’ll assume the current commit is bad, and the first ever commit was good.

git log

Will give a list of commits:

We need the first, which, for this repo, is:

3cbd757dd4e92d8ab2424c6a1e46a73bef23e056

Now we need to go through the process of setting up git bisect; the process is: you tell git that you wish to start a bisect:

git bisect start

Next, you tell git which commit is bad. In our case, that’s the current one:

git bisect bad

Finally, you tell it which was the last known good one – in our case, the first:

git bisect good 3cbd757dd4e92d8ab2424c6a1e46a73bef23e056

Now that we’re in a bisect, you could just tell git each time which is good and which bad (see the previous post on how you might do that), but here you can simply tell it to run the test:

git bisect run dotnet test GitBisectDemo/

This will then iterate through the commits and come back with the breaking commit:

That’s great, but in most cases you didn’t actually have a breaking test – something has stopped working, and you don’t know why or when. In these cases, you can write a new breaking test, and then give that to git bisect for it to tell you the last time that test passed.

Create a new test to determine where something broke

Firstly, the new test must not be checked in to source control, as this works by checking out code from previous releases. Then create your new test; for example:

namespace GitBisectDemo.Tests
{
    public class CalculationTests2
    {
        [Fact]
        public void DoCalculation_ReturnsCorrectValue()
        {
            // Arrange
            var calculationEngine = new CalculationEngine();

            // Act
            float result = calculationEngine.DoCalculation(2, 3);

            // Assert
            Assert.True(result > 4);
        }

    }
}

This is a new class, and it’s not checked into source control.

Executing a specific test from the command line

We now want to execute just one test, and you can do that using dotnet test like so:

dotnet test GitBisectDemo/ --filter "FullyQualifiedName=GitBisectDemo.Tests.CalculationTests2.DoCalculation_ReturnsCorrectValue"

You need to give it the full namespace and class name; we can now incorporate that into our git bisect:

git bisect start
git bisect bad
git bisect good 3cbd757dd4e92d8ab2424c6a1e46a73bef23e056

These are the same as before.

Note: if, at any time, you wish to cancel the bisect, it’s git bisect reset

Now, we feed the filtered test run into git bisect:

git bisect run dotnet test GitBisectDemo/ --filter  "FullyQualifiedName=GitBisectDemo.Tests.CalculationTests2.DoCalculation_ReturnsCorrectValue"

And we get a result when the new test would have broken.

That’s two cases covered. The final case is the situation whereby the thing that has broken cannot be determined by an automated test; say, for example, that an API call isn’t working correctly, or a particular process has slowed down. In this situation, we can have git bisect call out to an external executable.

Custom Console App

The first step here is to return a value (exit code) from the console app. In fact, this is deceptively simple:

static int Main(string[] args)
{
    var calculationEngine = new CalculationEngine();
    float result = calculationEngine.DoCalculation(3, 1);

    return (result == 4) ? 0 : -1;
}

Notice that all we’ve done here is change the Main signature to return an int. This console app could now be calling an external API, running a performance test, or anything that has a verifiable result.

Publish the console app

Because we’re calling this from another location, we’ll need to publish this test as a self-contained console app:

dotnet publish -r win-x64

Run the test

Again, the same set-up:

git bisect start
git bisect bad
git bisect good 3cbd757dd4e92d8ab2424c6a1e46a73bef23e056

Finally, we call the console app to run the test:

git bisect run GitBisectDemo/GitBisectDemo.ConsoleTest/bin/Debug/netcoreapp3.1/win-x64/GitBisectDemo.ConsoleTest.exe

References

https://docs.microsoft.com/en-us/dotnet/core/tools/dotnet-test

https://stackoverflow.com/questions/155610/how-do-i-specify-the-exit-code-of-a-console-application-in-net

Deferred Messages in Azure Service Bus

In Azure Service Bus, you can schedule a message to deliver at a later time, but you can also defer a message until a later time.

Scheduled Versus Deferred Messages

The difference here is subtle, but important: when you schedule a message, you’re telling the Service Bus to deliver that message at a time of your choosing, when you defer a message, you telling the Service Bus to hang onto a message that has been sent, until such time as you’re ready to receive it.

Why Would you Defer a Message?

The idea here is that you are not ready for the message – but you don’t want to hold up the queue. In this respect, it’s a little like the dead letter concept; that is, there is a message that’s essentially holding up the queue – however, in this case, there’s nothing wrong with the message itself.

Let’s imagine that we receive a message that a sales order has been created – we go to get the customer information for the sales order, and we find that the customer has yet to be created (such things are possible when you start engaging in eventually consistent systems): in this case, you could defer the message, and come back to it when the customer has been created.

Some Code – How to Defer a Message

Deferring a message is actually very simple:

var messageReceiver = new MessageReceiver(connectionString, QUEUE_NAME, ReceiveMode.PeekLock);
var message = await messageReceiver.ReceiveAsync();

var sequenceNumber = message.SystemProperties.SequenceNumber;
await messageReceiver.DeferAsync(message.SystemProperties.LockToken);

There’s three important concepts here:
1. The sequence number is very important: without it, the message is effectively lost; that’s because of (2)
2. You can receive a message after this, and you will never see the deferred message again until you purposely receive it, which brings us to (3)
3. To retrieve this message, you must explicitly ask for it.

To receive the deferred message you simply pass in the sequence number:

var messageReceiver = new MessageReceiver(connectionString, QUEUE_NAME, ReceiveMode.PeekLock);            
var message = await messageReceiver.ReceiveDeferredMessageAsync(sequenceNumber);

await messageReceiver.CompleteAsync(message.SystemProperties.LockToken);

The deferred message will never time out. Messages have a “Time to Live”, after which they get moved to the Dead Letter Queue; but once a message is deferred, it will live forever, and must be received to remove it.

References

https://docs.microsoft.com/en-us/azure/service-bus-messaging/message-deferral

Creating a Running Game in VueJS – Part 4 – The Finish Line

This post follows on from a series on creating a game in Vue. If you’d like to start from the beginning, then go here.

In the previous post we refactored the single file index.html that we’d been working on into multiple component files, and created a new Vue templated application.

In this post, we’ll do some further refactoring, and we’ll add a finish line.

Reusing Components

Since we now have components, we should re-use them; otherwise, there’s not much point in them being components. Our Player object is just a game object, and since we now need a second game object, let’s rename Player to GameObject. We can also add an additional property; for now, it will simply allow us to see which object is which:

<template>
    <div v-bind:style="location">
        
    </div>
</template>
<script>
export default {
  name: 'GameObject',
  props: {
    type: String,
    location: String
  }
}
</script>

We’ll change the template in App.vue, too:

<template>
    <GameObject
        v-bind:location="playerLocation"
        v-bind:type="player">
    </GameObject>
    <Timer 
        v-bind:seconds="secondsRemaining">
    </Timer>
    <GameObject
        v-bind:location="finishLineLocation"
        v-bind:type="finish-line">
    </GameObject>
</template>

As you can see, we’ve changed the data a little: instead of location we now have two pieces of computed data (in fact one isn’t really computed, but we’ll come back to that later):

computed: {                    
    playerLocation: function() {
        return 'width:10px; height:10px; left:' + this.playerX + 'px; top:' + this.playerY + 'px; border:1px solid #000; position: absolute;';
    },
    finishLineLocation: function() {
        return 'width:3px; height:300px; left:500px; top:50px; border:1px solid #000; position: absolute;';
    },

If you run that now, you’ll see the finish line; but alas we can “run” straight past the finish line and nothing happens!

Collision – have we won, or lost?

The first thing we’ll do here is create a new component: GameFinished. This will simply display some text for now saying whether you won or lost. The code inside the component will be very straightforward:

<template>
  <p>Game is finished, you {{ wonOrLost }}</p>
</template>
<script>
  export default {
    name: 'GameFinished',
    props: {
      isWon: Boolean
    },
    computed: {
      wonOrLost: function() {
        return this.isWon ? "Won" : "Lost";
    }
  }
}
</script>

We’ll need to both import and register the component. If you don’t, you’ll start getting errors such as

error ‘GameFinished’ is defined but never used no-unused-vars

Or:

error ‘GameFinished’ is not defined no-undef

To import the component, you’ll need this in App.vue:

<script>
    import GameObject from './components/GameObject.vue';
    import Timer from './components/Timer.vue';
    import GameFinished from './components/GameFinished.vue';

And registering is done slightly further down:

components: {    
    GameObject,
    Timer,
    GameFinished
},

We’ll add a new data property:

data: function() {                    
    return {
	. . . 
        isGameFinished: false

We’ll add a new computed function that will tell us whether we’ve won:

playerWon: function() {
    return this.isGameFinished && (this.secondsRemaining > 0);
}

And finally, the collision detection. Inside the Update method, we’ll just check the player position against the finish line:

update() {
    this.playerX += this.speed;
    if (this.speed > 0) {
        this.speed -= 0.01;
    } else {
        this.speed = 0;
    }
    this.timeNow = new Date().getTime();
    // Collision check
    if (this.playerX > this.finishLine) {
        this.isGameFinished = true;
    }
}

Where is the finish line?

Our last piece of refactoring will be to set the finish line based on a data property:

data: function() {                    
    return {
        . . . 
        finishLine: 500,

Now let’s tweak out finishLineLocation:

finishLineLocation: function() {
    return 'width:3px; height:300px; left:' + this.finishLine + 'px; top:50px; border:1px solid #000; position: absolute;';
},

In the next post, we’ll tweak the controls a little, and we’ll add some graphics.