Haskell Legacy: Introduction
A long time ago, I was asked to write on polysemy and Yesod integration, on another hand, I was also asked on the best way to migrate from regular, state-persisting based, legacy API, to event source system.
Note: I have never used Yesod before, so it won't be difficult for me to come up with legacy code.
In order to do that, let's see what we have: it's a train reservation API.
We can create trains, (un-)book in them.
It's described as such:
mkYesod
"TrainMasterAPI"
It's usable as simply as:
$ curl http://localhost:3000/train --json '{"departureDate": "2024-02-15", "departureStation": "Lyon", "arrivalStation": "Zurich"}'
{
"id": 2
}
$ curl http://localhost:3000/booking/2 --json '{"travelerName": "Alice"}'
{
"id": 4
}
$ curl http://localhost:3000/booking/2 --json '{"travelerName": "Bob"}'
{
"id": 5
}
$ curl http://localhost:3000/train/2
{
"arrivalStation": "Zurich",
"departureDate": "2024-02-15",
"departureStation": "Lyon",
"travelers": [
{
"bookingId": 4,
"travelerName": "Alice"
},
{
"bookingId": 5,
"travelerName": "Bob"
}
]
}
The code is designed around a simple database scheme (based on parsistant
):
share
[mkPersist sqlSettings, mkMigrate "migrateAll"]
I won't paste all the code here, but Handler
s are really tightly coupled to
the database:
data CreateTrainRequest = CreateTrainRequest
{ departureDate :: T.Text,
}
deriving stock (Eq, Show, Generic)
deriving anyclass (FromJSON, ToJSON)
newtype CreatedResponse a = CreatedResponse
{ id :: a
}
deriving stock (Eq, Show, Generic)
deriving anyclass (FromJSON, ToJSON)
postCreateTrainR = do
train <- requireCheckJsonBody @_ @CreateTrainRequest
trainId <-
runDB $
insert
Train
{ trainDepartureDate = train.departureDate,
trainDepartureStation = train.departureStation,
trainArrivalStation = train.arrivalStation
}
returnJson $ CreatedResponse trainId
It cannot be simpler than that (while remaining interesting), we'll follow the following plan to tackle it:
- Add few tests
- Extract logic from
Handler
s - Introduce event sourcing
- Substitute event sourcing to current implementation
- Introduce effects