Extracting the Delivery Service - Step 2, Split the database
The previous post described the first step of the refactoring process, which consisted of moving the delivery management code into its own ftgo-delivery-service
module.
It left the database unchanged and the newly defined JPA @Entity
classes in the ftgo-delivery-service
module were mapped to the existing database tables.
The Delivery
entity was mapped to the Order
entity’s ORDERS
table.
The second step of the refactoring process splits the database and defines a separate ftgo_delivery_service
database for the ftgo-delivery-service
module.
The following diagram shows the resulting structure:
The changes are primarily in this Git commit.
About the database migrations
The following Flyway-based schema migrations in ftgo-flyway/src/main/resources/db/migration
transform the database:
V2__split_courier.sql
V3__replica_restaurant.sql
V4__extract_into_delivery.sql
V5__FK_constraints.sql
These migrations create the tables in the ftgo_delivery_service
database and populate them with data from the monolith’s ftgo
database.
They also define triggers, which replicate data between the two databases.
Some triggers replicate updates to data owned by the FTGO monolith, such as Couriers
and Restaurants
, to ftgo-delivery-service
module’s database.
The other triggers replicate changes to data owned by the ftgo-delivery-service
module to the monolith’s database in order to make it accessed by the read-only columns described in the previous post.
For example, when the ftgo-delivery-service
updates Courier.availability
a trigger updates the corresponding column in the ftgo
database.
Let’s take a look at each of these schemas.
V2__split_courier.sql
This migration defines the courier
and courier_actions
tables in the ftgo_delivery_service
database and populates them with data from the ftgo.courier
and ftgo.courier_actions
tables.
It defines several triggers that synchronize data between the two schemas.
The first two replicate changes made to the ftgo_delivery_service
database to the ftgo
database:
ftgo_delivery_service.courier_availability_updated
- replicatesftgo_delivery_service.courier.available
toftgo.courier.available
ftgo_delivery_service.courier_actions_created
- replicates inserts intoftgo_delivery_service.courier_actions
toftgo.courier.courier_actions
(TODO what about deletes)
The other two triggers replicate changes made to the ftgo
database to the ftgo_delivery_service
database:
ftgo.courier_created
- replicates inserts intoftgo.courier
toftgo_delivery_service.courier
ftgo.courier_updated
- replicates updates offtgo.courier
toftgo_delivery_service.courier
V3__replica_restaurant.sql
This migration defines the restaurant
table in the ftgo_delivery_service
database and populates it with restaurants from ftgo.restaurant
.
It also defines a trigger that replicates inserts into ftgo.restaurant
table to the ftgo_delivery_service.restaurant
table.
TODO what about UDs
V4__extract_into_delivery.sql
This migration defines the delivery
table in the ftgo_delivery_service
database and populates it with deliveries from ftgo.delivery
.
It also defines a trigger that replicates updates of the ftgo_delivery_service.assigned_courier_id
column to the ftgo.delivery
table.
V5__FK_constraints.sql
This migration creates foreign key constraints between the newly defined tables.
About the code changes
In addition to the schema changes, there are a few code changes.
First, the JPA entities in the ftgo-delivery-module
are mapped to new databases tables.
For example, Delivery
is mapped to the delivery
table:
@Entity
@Table(name = "delivery", catalog = "ftgo_delivery_service")
@Access(AccessType.FIELD)
@DynamicUpdate
public class Delivery {
...
Second, the DeliveryState
enum is simplified since it no longer needs to mirror OrderState
.
It now just defines values that correspond to the state of the Delivery
.
Third, because Delivery
no longer shares a table with Order
the DeliveryService.scheduleDelivery()
method can no longer load the Delivery
.
Instead, it must create the Delivery
:
public class DeliveryServiceImpl implements DeliveryService, DeliveryCourierService {
private DeliveryRepository deliveryRepository;
public void scheduleDelivery(LocalDateTime readyBy, Long orderId, long restaurantId, Address deliveryAddress) {
...
delivery = deliveryRepository.save(delivery);
...
}
...
What’s next
- Study the refactored code, which is the
extract-delivery-service-02-split-db
branch in the main repository. This refactoring is primarily in this commit. - Read chapter 13 of my book Microservices patterns, which covers refactoring to microservices
- Read the next step, which extracts the
Delivery Service
. - Talk to me about my microservices consulting and training services