Principal Software Engineer at Allscipts in Malvern, Pennsylvania, Microsoft Windows Dev MVP, Husband, Dad and Geek.
51813 stories
·
22 followers

Selective Projects Loading using Solution Filter in Visual Studio

1 Share

Solution Filter in Visual Studio allows a faster load of the solution with selective projects. When we are working on a large solution with several projects, we may not work with all the projects together. Sometimes, specific developers only focus on a set of projects. Solution Filter in Visual Studio allows us to select only the required projects… Read More »

The post Selective Projects Loading using Solution Filter in Visual Studio appeared first on Daily .NET Tips.

Read the whole story
alvinashcraft
8 hours ago
reply
West Grove, PA
Share this story
Delete

Christian Geuer Pollmann on Erlang and Elixir

1 Share

Episode 594

Christian Geuer Pollmann on Erlang and Elixir

Christian Geuer-Pollmann describes the Erlang ecosystem, the Elixir language, and open source Azure tools he has built with Elixir.

Links:

https://github.com/chgeuer
https://twitter.com/chgeuer
http://blog.geuer-pollmann.de

Read the whole story
alvinashcraft
8 hours ago
reply
West Grove, PA
Share this story
Delete

#475 – An Interview with Christina Cyr

1 Share

Welcome Christina Cyr, CEO of dToor and the Cyrcle Phone





Download audio: http://traffic.libsyn.com/theamphour/TheAmpHour-475-ChristinaCyr.mp3
Read the whole story
alvinashcraft
8 hours ago
reply
West Grove, PA
Share this story
Delete

10 Important Git Commands that Every Developer Should Know

1 Share
Git is an important part of daily programming (especially if you're working with a team) and is widely used in the software industry. Since there are many various commands to use, mastering Git takes time but some commands are being used more frequently (mostly daily) and in this post, I

Read the whole story
alvinashcraft
10 hours ago
reply
West Grove, PA
Share this story
Delete

Kubernetes testing with KIND

2 Shares

Kubernetes in Docker (KIND)

There are many solutions for creating a local test Kubernetes environment, such as minikube or MicroK8s, but a new project called KIND offers a fresh approach that may interest Kubernetes developers and administrators.

KIND stands for Kubernetes IN Docker, and as the name suggests, it creates a Kubernetes cluster using Docker to host the nodes. This is a novel approach, that takes advantage of Docker’s easy, self-contained deployments and cleanup to create the test Kubernetes infrastructure.

KIND Installation

Make sure you have Docker and Go installed, and then install KIND with the command:

GO111MODULE="on" go get sigs.k8s.io/kind@v0.6.1

This will place the kind executable in the directory $GOPATH/bin/kind, which will be ~/go/bin/kind by default.

Assuming the Go bin directory is in the PATH, build a test cluster with the command:

kind create cluster --name mycluster

The first cluster takes a little while to download KIND Docker images, although subsequent clusters take less than a minute to create.

KIND will add the new cluster details as a context to your ~/.kube/config file, so you can test the cluster is up and running with the command:

kubectl cluster-info --context kind-mycluster

You can set this context as the default with the command:

kubectl config use-context kind-mycluster

Using the KIND Kubernetes cluster

The most immediate issue I ran into when using KIND was accessing the services deployed to the cluster.

By default KIND only exposes the Kubernetes API server. This means kubectl will work as expected. So you can deploy to the cluster and query resources, but accessing your services requires some extra work.

A solution is to use kubectl as a proxy:

kubectl proxy --port=8080

Kubernetes services are then available through a specifically formed URL like http://localhost:8080/api/v1/namespaces/default/services/webserver:http-web/proxy/.

The Kubernetes documentation has more details on these proxy URLs:

To create proxy URLs that include service endpoints, suffixes, and parameters, you simply append to the service’s proxy URL: http://kubernetes_master_address/api/v1/namespaces/namespace_name/services/[https:]service_name[:port_name]/proxy

Port forwarding removes the need to construct special URLs. Start port forwarding with a command like:

kubectl port-forward svc/webserver 8081:80

The service is now available on the local port of 8081, directing traffic to the service port 80. This means the URL http://localhost:8081 can be used to access the service.

You can also use port forwarding on an ingress controller:

kubectl port-forward svc/nginx-release-nginx-ingress 8081:80

This command allows you to access services via any ingress rules you have configured.

The KIND documentation also provides some additional details on how to expose ingress controllers for a more permanent solution.

First impressions

Once I got around the issue of accessing my services, KIND performed remarkably well for a beta release. External tools like Helm worked fine, and I could deploy custom dashboards to the cluster.

I appreciated the fact the KIND was so self-contained. Because everything is a Docker container, creating the cluster was quick, and when it was cleaned up afterward there was nothing left running on the system.

Conclusion

Getting a Kubernetes cluster running locally isn’t that difficult these days, but KIND makes it especially easy to create a cluster. Admittedly, Kubernetes running on Docker to orchestrate Docker is a little mind bending, but it can’t be beaten for convenience.

The real value of KIND is the ability to run it as part of automated tests. I didn’t have a use case for this personally, but I’m sure it lives up to the promise.

I’ll seriously consider using KIND over minikube for local testing from now on.

Read the whole story
sbanwart
8 hours ago
reply
Akron, OH
alvinashcraft
10 hours ago
reply
West Grove, PA
Share this story
Delete

Building microservices through Event Driven Architecture part10: Handling updates

1 Share

This tutorial is the  10th part of a series : Building microservices through Event Driven Architecture.

The previous step is about building microservices through Event Driven Architecture part9: Implementing EventSourcing on Application : http://logcorner.com/building-microservices-through-event-driven-architecture-part8-implementing-eventsourcing-on-application/

During this journey, I will  talk about how to handle updates on a Event Sourcing System.

So , in the prevoius steps , I have stored all business changes of the system as events instead of storing the current state.  and I  rebuild the current state by applying all the events to the aggregate.

I have builded a list of domain events :  business changes happened in the past expressed in the  Ubiquitous Language : ex ThePackageHasBeenDeliveredToCustomer.

Domain Events are immutable, when a event happen it cannot be changed.

So, to correct a mistake on an event, I have to create a compensation event with correct values like bank account transactions.

The aggregate records committed events and protects  business invariants. It is the transaction boundary.  To deal  with concurrency  I will use Optimistic Concurrency Control (OCC)   with versioning.

Without acquiring locks each transaction verifies that no other transaction has modified the data it has read. If not the transaction is committed,  if yes the transaction rolls back and can be restarted.

With versionning , the user reads the current state of the aggregate,  then send commands with the version number, if the version number match the version of the aggregate then the transaction is committed.

If the version number does not match the version of the aggregate, in this case it means that the data has  been updated by someone else. So the user should read again the data to get the correct version and retry.

In this tutorial, I will shwo how to update the Speech Entity. It has the following properties  : Title, Description, Url and Type.  So the update of each property is an event and should be stored on event store.

HANDLING UPDATE ON DOMAIN MODEL

HANDLING UPDATE TITLE

TEST CASE 1 : ChangeTitle  when title is null or empty should raise ArgumentNullAggregateException:

Here I will test that if the Title is NullOrEmpty then, the system should raise an exception.

ChangeTitleNullTitle

TEST CASE 2 : ChangeTitle  when expected version is not equals to aggregate version  should raise ConcurrencyException:

Here I will test that if the expectedVersion is not equals to the aggregateVersion then, the system should raise an exception.

Because I create a new speech, the aggregate version is equals to zero , so if I set expectedVersion to one, the test should raise an exception.

ChangeTitleInvalidVersion

TEST CASE 3 : ChangeTitle  with valid arguments  should apply SpeechTitleChangedEvent :

Here I will test that if no errors , then the newTitle  should be applied to the title of the speech. In other words : Speech.Title = “value of new title after updates”

ChangeTitleValidArguments

 ChangeTitle  Final implementation :

The final implementation of ChangeTitle should look like this.

Very simple, I the title is not null or empty, apply a SpeechTitleChangedEvent .  The apply function sets the speech title with the value of the event title.

The code that checks the version of the aggregate was developed in the previous steps ( see the aggregateroot.cs class)

public void ValidateVersion(long expectedVersion)
{
if (Version != expectedVersion)
{
throw new ConcurrencyException($@”Invalid version specified : expectedVersion = {Version}  but originalVersion =                             {expectedVersion}.”);
}
}

SpeechTitleChangedEvent

HANDLING UPDATE DESCRIPTION, URL AND TYPE

ChangeDescription, ChangeUrl and ChangeType should follow the same scenario as ChangeTitle

HANDLING UPDATE ON APPLICATION

HANDLING UPDATE TITLE

TEST CASE 1 : Handling Update when Command is null  should raise ApplicationArgumentNullException :

Here I will test that if the updateCommand is null, then the system should raise an exception.

So I should mock all external dependencies : IUnitOfWork, ISpeechRepository and IEventSourcingSubscriber

HandlingUpdateWhenCommandIsNullShouldRaiseApplicationArgumentNullException

TEST CASE 2 : Handling update when speech does not exist  should raise ApplicationNotFoundException:

Here I will test that if the speech to update does not exist, then the system should raise an exception.

I have to arrange my repository ao that it returns a null speech with mock  :

moqEventStoreRepository.Setup(m => m.GetByIdAsync<Domain.SpeechAggregate.Speech>(command.SpeechId))
.Returns(Task.FromResult((Domain.SpeechAggregate.Speech)null));

and that’s it.

HandlingUpdateWhenSpeechDoesNotExistShouldRaiseApplicationNotFoundException

TEST CASE  3 : Handling Update when Command is not null should update speech Title :

Here I will test that if the command is not null and the speech to update exist , then the title should be updatet.

A way to verify that the Speech Title is modified is to check it’s value before sending it to repository :

moqSpeechRepository.Verify(m =>
m.UpdateAsync(It.Is<Domain.SpeechAggregate.Speech>(n =>
n.Title.Value.Equals(command.Title)
)),Times.Once);

 

HandlingUpdateWhenCommandIsNotNullShouldUpdateSpeechTitle_1

HandlingUpdateWhenCommandIsNotNullShouldUpdateSpeechTitle_2

TEST CASE  4 : Handling Update when Expected version is not equal to aggregate version should raise ConcurrencyException :

Here I will test that if the expectedVersion is not equals to the aggregateVersion, then the system should raise an exception.

HandlingUpdateWhenExpectedVersionIsNotEqualToAggregateVersionShouldRaiseConcurrencyException

HANDLING UPDATE ON REPOSITORY

HANDLING UPDATE 

TEST CASE 1 : Handling Update when Speech is null  should raise RepositoryArgumentNullException :

HandlingUpdateWhenSpeechIsNullShouldRaiseRepositoryArgumentNullException

TEST CASE 2 : Handling Update when the speech  does not exist should raise NotFoundRepositoryException 

HandlingUpdateWhenTheSpeechDoesNotExistShouldRaiseRepositoryNotFoundException

 TEST CASE 3 : Handling Update when the speech  is valid and exist should perform update

HandlingUpdateWhenTheSpeechIsValidAndExistShouldPerformUpdate

And the final implementation

UpdateAsyncFinal

HANDLING UPDATE ON PRESENTATION

HANDLING UPDATE 

TEST CASE 1 : Update Speech When ModelState Is Invalid Should Return BadRequest :

UpdateSpeechWhenModelStateIsInvalidReturnBadRequest

TEST CASE 2 : UpdateSpeech When An Exception Occurred Should Raise InternalServerError

Idem with register speech (ExceptionMiddleware)

 

TEST CASE 3 : Update Speech When ModelState Is Valid With No Errors Should Return Ok

UpdateSpeechWhenModelStateIsValidWithNoErrorsShouldReturnOk

And the final implementation

 

Coverage

TEST WITH POSTMAN

Hit F5 and start postman and sql server.

Let’s start sql server and see what’s going on
Here I have to table’s [dbo].[Speech] and [dbo].[EventStore] , let us run a select query , you can see that these 2 tables are empty.

EmptyResults

Let us start postman and run a post request to create a speech : http://localhost:62694/api/speech

Ok lets go

the postman scripts are here : LogCorner.EduSync.Command\src\Postman\BLOG.postman_collection.json

postspeech

Now I should have a newly created speech and a event LogCorner.EduSync.Speech.Domain.Events.SpeechCreatedEvent, LogCorner.EduSync.Speech.Domain, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
Note that the version is equals to 0.
For each new speech, the version should be equal to zero.

If I inspect the payload, I must see my event

 

InsertedResult

{
“Title”: {
“Value”: “Le Lorem Ipsum est simplement du faux texte”
},
“Url”: {
“Value”: “http://www.yahoo_1.fr”
},
“Description”: {
“Value”: “Le Lorem Ipsum est simplement du faux texte employé dans la composition et la mise en page avant impression. Le Lorem Ipsum est le faux texte standard de l’imprimerie depuis les années 1500, quand un imprimeur anonyme assembla ensemble des morceaux de texte pour réaliser un livre spécimen de polices de texte”
},
“Type”: {
“Value”: 3
},
“AggregateId”: “7c8ea8a0-1900-4616-9739-7cb008d37f74”,
“EventId”: “a688cc8a-ed56-4662-bbad-81e66ed917a0”,
“AggregateVersion”: 0,
“OcurrendOn”: “2020-01-19T15:49:59.3913833Z”
}

 

To update the title of the speech, i run the following request http://localhost:62694/api/speech
it is a put request .

I grab the identifier of the newly created speech CF17D255-9991-4B7B-B08E-F65B54AA9335
Let us copy from sql and paste it on request body.

Ok, Now i can run the put query

putspeech

Come back to sql server to verify the result

SELECT * FROM [dbo].[Speech]

SELECT *  FROM [dbo].[EventStore]

I should see the updated title and a new event LogCorner.EduSync.Speech.Domain.Events.SpeechTitleChangedEvent.

The version should be 1 and the payload should be the update event

{
“Title”: “UPDATE_1__Le Lorem Ipsum est simplement du faux texte”,
“AggregateId”: “7c8ea8a0-1900-4616-9739-7cb008d37f74”,
“EventId”: “de253f69-ea89-4a54-8927-e09553cc43c7”,
“AggregateVersion”: 1,
“OcurrendOn”: “2020-01-19T15:55:14.1734365Z”
}

updatedResult

Cource code of this article is available here  (Feature/Task/EventSourcingApplication)

https://github.com/logcorner/LogCorner.EduSync.Speech.Command/tree/Feature/EventSourcingHandlingUpdates

Regards

18 total views, 8 views today

Read the whole story
alvinashcraft
10 hours ago
reply
West Grove, PA
Share this story
Delete
Next Page of Stories