One idea we could try is to implement the “Create a donation event” feature in the same way as our donor sign-up feature.
Architecturally they would look the same:
If we transformed it into steps, it would also be:
POST
request with a JSON payloadevent
argumentI’ll go with /donation/create
.
Our ~/serverless_workshop/savealife/app.py
file can be extended to include the highlighted lines:
import logging
from os import getenv
from chalice import Chalice
from chalicelib.db import get_app_db
try:
from dotenv import load_dotenv
load_dotenv()
except ImportError:
pass
first_name = getenv("WORKSHOP_NAME", "ivica") # replace with your own name of course
app = Chalice(app_name=f"{first_name}-savealife")
app.log.setLevel(logging.DEBUG)
@app.route("/donor/signup", methods=["POST"])
def donor_signup():
body = app.current_request.json_body
app.log.debug(f"Received JSON payload: {body}")
return get_app_db().donor_signup(body)
@app.route("/donation/create", methods=["POST"])
def donation_create():
body = app.current_request.json_body
app.log.debug(f"Received JSON payload: {body}")
return get_app_db().donation_create(body)
When it comes to the JSON payload itself I would propose we keep things simple again. What potential donors should know about a blood donation are 4 pieces of information: in which city is it being held, on which date and at what time, which blood types are needed and what is the location. So, something like this:
Very similar to how we copy-pasted existing code for the Lambda function, our blood donation persistence layer
can be copy-pasted from the donor_signup
function. Add the highlighted lines to
~/serverless_workshop/savealife/chalicelib/db.py
class SavealifeDB:
def __init__(self, table, logger):
# ... SNIP ...
def donation_create(self, donation_dict):
try:
self._table.put_item(
Item={
"city": donation_dict.get("city"),
"datetime": donation_dict.get("datetime"),
"address": donation_dict.get("address")
}
)
self._logger.debug(
f"Inserted donation '{donation_dict.get('city')}, {donation_dict.get('address')}' "
f"into DynamoDB table '{self._table}'"
)
return True
except Exception as exc:
self._logger.exception(exc)
Run the local server chalice local --autoreload
and hit the endpoint we just created.
http :8000/donation/create city=Haarlem blood_types="A-" address="Main Street"
Does it work? What happened?
The endpoint, from the API perspective, works just fine but nothing will be saved to the DynamoDB table. That is because of how our DynamoDB table was created:
Having logging configured help us to clearly see the issue; first_name
is our primary key and the expected attribute.
http -b POST :8000/donation/create city=Haarlem address="Main street"
will show something along the lines of:
Back to the drawing board…