The to-do manager service

The to-do manager service is the service that will help our users manage their todo items. This service provides the functionality for the user to create a new list and add items to the list. For this, the only requirement is that the user should be authenticated.

To work correctly, the service will require the presence of a list database model, which will be used to store the information about the user-created todo list and an items model, which will contain the list of items for a particular todo list.

The following snippet of code implements these models:

'''
File: models.py
Description: The models for the todo service.
'''
from todo_service.todo_service import db
import datetime

class List(db.Model):
"""The list database model.

The list database model is used to create a new todo list
based on the input provided by the user.
"""

id = db.Column(db.Integer, primary_key=True)
user_id = db.Column(db.Integer, nullable=False)
list_name = db.Column(db.String(25), nullable=False)
db.UniqueConstraint('user_id', 'list_name', name='list_name_uiq')

def __repr__(self):
"""Provide a representation of model."""
return "<List {}>".format(self.list_name)

class Item(db.Model):
"""The item database model.

The model is used to store the information about the items
in a particular list maintained by the user.
"""

id = db.Column(db.Integer, primary_key=True)
list_id = db.Column(db.Integer, db.ForeignKey(List.id))
item_name = db.Column(db.String(50), nullable=False)
db.UniqueConstraint('list_id', 'item_name', name='item_list_uiq')

def __repr__(self):
"""Provide a representation of model."""
return "<Item {}>".format(self.item_name)

Once these models have been developed, the next thing we have to do is implement the APIs.

For the to-do manager service, the following APIs will be in place, providing the interaction endpoints for the service:

  • /list/new: This API endpoint takes in the name of the list to be created and creates a new list.
  • /list/add_item: This API endpoint takes in the list of the items that need to be added to the list and the name of the list in which the items are supposed to be added. Once validated, the items are added to the list.
  • /list/view: This API endpoint takes the name of the list for which the contents need to be displayed and displays the content of the list.

The following snippet of code shows the endpoint implementations for the service:

def check_required_fields(req_fields, input_list):
"""Check if the required fields are present or not in a given list.

Keyword arguments:
req_fields -- The list of fields required
input_list -- The input list to check for

Returns:
Boolean
"""

if all(field in req_fields for field in input_list):
return True
return False


def validate_user(auth_token):
"""Validates a user and returns it user id.

Keyword arguments:
auth_token -- The authentication token to be used

Returns:
Integer
"""

endpoint = user_service + '/auth/validate'
resp = requests.post(endpoint, json={"auth_token": auth_token})
if resp.status_code == 200:
user = resp.json()
user_id = user['user_id']
return user_id
else:
return None

@app.route('/list/new', methods=['POST'])
def new_list():
"""Handle the creation of new list."""

required_fields = ['auth_token', 'list_name']
response = {}
list_data = request.get_json()
if not check_required_fields(required_fields, list_data.keys()):
response['message'] = 'The required parameters are not provided'
return jsonify(response), 400

auth_token = list_data['auth_token']

# Get the user id for the auth token provided
user_id = validate_user(auth_token)

# If the user is not valid, return an error
if user_id is None:
response['message'] = "Unable to login user. Please check the auth token"
return jsonify(response), 400

# User token is valid, let's create the list
list_name = list_data['list_name']
new_list = List(user_id=user_id, list_name=list_name)
db.session.add(new_list)
try:
db.session.commit()
except Exception:
response['message'] = "Unable to create a new todo-list"
return jsonify(response), 500
response['message'] = "List created"
return jsonify(response), 200

@app.route('/list/add_item', methods=['POST'])
def add_item():
"""Handle the addition of new items to the list."""

...
# The complete code for the service can be found inside the assisting code repository for the book

With the preceding code in place, we are now ready with our to-do manager service, which will help us create and manage our to-do lists through the use of RESTful APIs.

But before we get the to-do manager service to execute, we need to remember one important thing. The service is dependent upon the user service to perform any kind of user authentication and to fetch information about the user profile. For this to happen, our to-do manager needs to know where the user service is running so that it can interact with the user service. For this example, we achieve this by setting up a configuration key for the user service endpoint inside the to-do manager service configuration file. The following snippet shows the contents of the to-do manager service configuration file:

DEBUG = False
SECRET_KEY = 'du373r3uie3yf3@U#^$*EU9373^#'
BCRYPT_LOG_ROUNDS = 5
SQLALCHEMY_DATABASE_URI = 'sqlite:///todo_service.db'
SQLALCHEMY_ECHO = False
USER_SERVICE_ENDPOINT = 'http://localhost:5000'

To get the to-do manager service running, the following command needs to be executed from inside the todo_service directory, inside the repository:

python3 run.py

Once the command executes successfully, the to-do manager service will be available at http://localhost:5001/.

Once the service is up and running, we can utilize its API to manage our inventory. For example, if we wanted to create a new to-do list, all we need to do is send an HTTP POST request to the http://localhost:5001/list/new API endpoint, passing the following keys as JSON formatted inputs:

  • auth_token: This is the authentication token the user receives after successfully logging in with the user service using the http://localhost:5000/auth/login API endpoint
  • list_name: This is the name of the new list that is to be created

Once the API endpoint call is made, the to-do manager service first makes an attempt to validate the auth token provided in the API call by interacting with the user service. If the auth token is validated, the to-do manager service then receives a user ID that is used to identify the user. With this complete, the to-do manager service creates an entry for the new to-do list inside its database against the user ID that has been retrieved.

This was a simple workflow of the to-do manager service.

Now that we understand how we can build a simple microservice, we can now focus on some interesting topics regarding the microservices architecture. Did you notice how we informed our to-do manager service of the presence of the user service? We utilized a configuration key to achieve this. Using the configuration key is by no means a bad option when all you have is two or three services that, no matter what happens, will always run on the same endpoints. However, this approach breaks down badly when the microservices number even moderately more than two or three services, which may run anywhere on the infrastructure.

To add on to these troubles, the problem intensifies even further if new services are being brought into production frequently to add new features to the application. At this point, we will need something better that should not only provide an easy way to identify the new services, but also automatically resolve their endpoints.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.17.79.20