Let’s Build A Service

Ray Kahn
5 min readMay 10, 2018

--

Remember this:

/home/{user}/github/{name of service}-services (top level)

|__ src/ (all your code)

|__ package.json (installed packages, description, entry point, etc)

|__ start-script.sh (start the service)

|__ stop-script.sh (stop the service)

|__ Dockerfile (all the commands a user could call on the command line to assemble an image)

|__ npm-shrinkwrap.json (locks you in to your dependency versions)

|__ integration-test/

|__ node_modules/ (all the installed packages when you execute npm instal <package_name>)

|__ create-image.sh (script to create a Docker image, which calls the Dockerfile)

We are going to build a micro service with the following API end points:

/provider/:pid — returns a single provider (or doctor)

/providers/:types/:latlng/:radius/:limit/:skip — an array of providers based on given latitude and longitude of a user.

What You Will Need

You will need to take a look at the package.json file to see what’s needed for this service. But here’s a quick look:

“express”: “*”,
“helmet”: “*”,
“http-status”: “*”,
“mongodb”: “*”,
“morgan”: “*”,
“shrinkwrap”: “⁰.4.0”,

mongoose is also needed. What’s mongoose you ask?

Mongoose provides a straight-forward, schema-based solution to model your application data. It includes built-in type casting, validation, query building, business logic hooks and more, out of the box.

Previously we covered the following:

Where to find the code

64,000 feet view

You need to know a few important facts about micro services that can help you understand, visualize really, how micro services work.

  • Each container will “contain” all of your services
  • Each service will use a unique port (3000, 3001, …)
  • There needs to be an API gateway that brings all your services under a single umbrella. In short a single point of entry to your application. It’s not a load balancer, but more akin to a “router”. This API gateway itself “lives” in a container with a unique port, 8080 usually.

Walk me through it already

The providers-service will have 2 end point API. These end-points will be defined in an api file named provider.js, under /src/api.

Of course you may add as many end points as your application needs. This is my simple api file.

If you notice, I am passing two objects to this module, an app (express object) and a model object. The model object is basically where your applications logic to interact with mongoDB will reside. Let’s look at that module next.

As you can see I am using mongoose schema because of controls and exactness imposed by schemas. Schemas also allow you to catch bugs earlier in the development cycle. In fact, most Mongo data usually has an implied structure anyway so why not use a schema. I am sure there are counter arguments to mine so please do let me know.

I am also taking advantage of cloning mechanism provided by Object.assign:

module.exports = Object.assign({},{connect});

This way the consumer of this module will not be affected by the changes that ProviderModel.js may undergo.

On To The Server

Before the server should be started we need to make sure that we have a connection to the mongoDB server. So our start-up script must first establish the connection, then call express to listen to a port that I have set in a configuration file. So let’s look at our start-up code.

Our start-up code is index.js at the top level of src/ directory.

A few things that you will notice is that I am also using event emitters to handle mongoose connection notification. If the defined emitter encounters an error from mongoDB server it will instead emit an error notification which the start up code handles.

start-up code — calls → dbConnection module — which in turn returns → either a connection object or an error.

The code above is fairly simple. I am using EventEmitter to handle mongoose connection.

On line 28 I call dbObject to get a connection to the mongodb server.

Once a connection is established we will instantiate our model object, see line 10 of index.js, see ProvideModel.js code above. When we have our model object we will start the server, line 13 of index.js.

If all goes well we should be able to test your code as a stand-alone server before containerizing it by executing the following command:

node src/
# should see the following
SUCCESS::providers-service: mongoose connection successful.
SUCCESS::providers-service: server started successfully.

And to test your server and code, open your browser and go to http://localhost:3000/provider/{provider id}.

And the second API is also working

I have not included all the code here but they are available on the Github repository.

But what about TDD?

Having a set of tests for your application allows you to make changes to your code with confidence, knowing that the tests have your back should you break anything. It’s possible to take things a step further and write your tests before you write the code; a practice known as Test-driven development (TDD).

Well let me tell you that’s a great advice. I use mocha as my preferred testing framework. Each module has it’s own {module name}.spec.js file (that’s how mocha picks up the right module to test). I won’t get into TDD since that’s a completely separate subject matter worthy of a separate blog.

Do we have a service container yet?

Not yet, but we are getting close… we still need to create the containerized version of our service, which we will do in the next part.

--

--