Skip to content

Instantly share code, notes, and snippets.

@mumez
Last active April 28, 2025 16:56
Show Gist options
  • Select an option

  • Save mumez/75f1b3cbd08035db6c5f45af7e1590ba to your computer and use it in GitHub Desktop.

Select an option

Save mumez/75f1b3cbd08035db6c5f45af7e1590ba to your computer and use it in GitHub Desktop.
Historia bank account sample code for Playground
HsModel subclass: #HtBankAccount
instanceVariableNames: 'name balance'
classVariableNames: ''
package: 'Historia-Examples-SimpleBank'!
!HtBankAccount methodsFor: 'accessing' stamp: '4/29/2025 00:42'!
name
^ name! !
!HtBankAccount methodsFor: 'accessing' stamp: '4/29/2025 00:42'!
name: anObject
name := anObject! !
!HtBankAccount methodsFor: 'accessing' stamp: '4/29/2025 00:42'!
balance
^ balance! !
!HtBankAccount methodsFor: 'accessing' stamp: '4/29/2025 00:42'!
balance: anObject
balance := anObject! !
!HtBankAccount methodsFor: 'initialization' stamp: '4/29/2025 01:20'!
initialize
name := ''.
balance := 0! !
!HtBankAccount methodsFor: 'mutations' stamp: '4/29/2025 01:20'!
mutateBalanceChange: newBalanceChange
self
mutate: HtBankAccountBalanceChanged
using: [ :ev | ev value: newBalanceChange ]! !
!HtBankAccount methodsFor: 'applying' stamp: '4/29/2025 01:20'!
applyBalanceChange: newBalanceChange
balance := balance + newBalanceChange! !
HsModelSpace subclass: #HtBankAccountSpace
instanceVariableNames: ''
classVariableNames: ''
package: 'Historia-Examples-SimpleBank'!
!HtBankAccountSpace methodsFor: 'actions' stamp: '4/29/2025 00:59'!
getBalanceAt: accountId
| acc |
acc := self modelAt: accountId.
^ acc balance! !
!HtBankAccountSpace methodsFor: 'actions' stamp: '4/29/2025 01:19'!
deposit: amount at: accountId
| acc |
acc := self modelAt: accountId.
acc mutateBalanceChange: amount.
self save: acc! !
!HtBankAccountSpace methodsFor: 'actions' stamp: '4/29/2025 01:20'!
withdraw: amount at: accountId
| acc |
acc := self modelAt: accountId.
acc mutateBalanceChange: amount negated.
self save: acc! !
!HtBankAccountSpace methodsFor: 'actions' stamp: '4/29/2025 01:05'!
transfer: amount from: fromAccountId to: toAccountId
| fromAcc toAcc |
fromAcc := self modelAt: fromAccountId.
toAcc := self modelAt: toAccountId.
fromAcc mutateBalanceChange: amount negated.
toAcc mutateBalanceChange: amount.
toAcc notify: #transferredTo withArguments: {
(#to -> toAccountId).
(#from -> fromAccountId).
(#amount -> amount) }.
self saveAll: {
fromAcc.
toAcc }! !
HsModelEventBridge subclass: #HtBankAccountMailBridge
instanceVariableNames: ''
classVariableNames: ''
package: 'Historia-Examples-SimpleBank'!
!HtBankAccountMailBridge methodsFor: 'initialization' stamp: '4/29/2025 01:14'!
initialize
super initialize.
self notificationAnnouncedDo: [ :annoncement |
annoncement kind = #transferredTo ifTrue: [
self handleTransferedToEvent: annoncement event ] ]! !
!HtBankAccountMailBridge methodsFor: 'event handling' stamp: '4/29/2025 01:15'!
handleTransferedToEvent: notificationEvent
| accountId mailAddress |
accountId := notificationEvent argsAt: 'to' ifAbsent: [ '' ].
mailAddress := self mailAccountSpace getMailAddressAt: accountId.
self externalMailService
sendMailTo: mailAddress
content: (self mailTemplateSpace
getContentAt: notificationEvent kind
values: notificationEvent arguments)! !
!HtBankAccountMailBridge methodsFor: 'accessing' stamp: '4/29/2025 01:16'!
mailAccountSpace
^ self! !
!HtBankAccountMailBridge methodsFor: 'accessing' stamp: '4/29/2025 01:16'!
externalMailService
^ self! !
!HtBankAccountMailBridge methodsFor: 'accessing' stamp: '4/29/2025 01:19'!
mailTemplateSpace
^ self! !
!HtBankAccountMailBridge methodsFor: 'mocking' stamp: '4/29/2025 01:15'!
getMailAddressAt: accountId
^ { ('00001' -> 'john.smith@example.com') } asDictionary
at: accountId
ifAbsent: [ '' ]! !
!HtBankAccountMailBridge methodsFor: 'mocking' stamp: '4/29/2025 01:15'!
sendMailTo: mailAddress content: mailContent
Transcript
cr;
show: ('## Send mail to: {1} content: {2}' format: {
mailAddress.
mailContent })! !
!HtBankAccountMailBridge methodsFor: 'mocking' stamp: '4/29/2025 01:15'!
getContentAt: templateKey values: templateValues
^ 'You just received {amount} from {from}' format: templateValues! !
HsValueChanged subclass: #HtBankAccountBalanceChanged
instanceVariableNames: ''
classVariableNames: ''
package: 'Historia-Examples-SimpleBank'!
!HtBankAccountBalanceChanged methodsFor: 'applying' stamp: '4/29/2025 00:56'!
applyTo: target
target applyBalanceChange: self value! !
"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!
HtBankAccountBalanceChanged class
instanceVariableNames: ''!
!HtBankAccountBalanceChanged class methodsFor: 'accessing' stamp: '4/29/2025 01:21'!
typeName
^ self name! !
!HtBankAccountBalanceChanged class methodsFor: 'class initialization' stamp: '4/29/2025 01:21'!
initialize
self register! !
HtBankAccountBalanceChanged initialize!
"Create a ModelSpace"
spaceId := 'bank-account-app-1'.
accId := '00001'.
modelSpace := HtBankAccountSpace spaceId: spaceId.
"Register the model to the ModelSpace"
bankAccount1 := modelSpace putModelOf: HtBankAccount id: '00001' withArguments: {'name'->'John Smith'}.
"Retrieve the model by its ID"
modelSpace modelAt: '00001'. "-> returns bankAccount1"
"Deposit money into the account"
modelSpace deposit: 100 at: '00001'.
"Withdraw money from the account"
modelSpace withdraw: 30 at: '00001'.
"Retrieve the current balance"
modelSpace getBalanceAt: accId. "-> returns 70"
"Retrieve events"
modelSpace eventJournalStorage allEvents.
modelSpace eventVersionsReversedFromLast: 5.
"Saving snapshots"
modelSpace saveSnapshot.
modelSpace deposit: 100 at: accId.
modelSpace saveSnapshot.
"Snapshot versions"
modelSpace snapshotStorage listSnapshotVersions.
snapVersions := modelSpace snapshotVersionsReversedFromLast: 2.
"Loading snapshots"
modelSpace loadSnapshot: snapVersions last.
modelSpace getBalanceAt: accId.
modelSpace loadSnapshot: snapVersions first.
modelSpace getBalanceAt: accId.
"Create another ModelSpace"
modelSpace2 := HtBankAccountSpace spaceId: spaceId.
modelSpace2 models isEmpty.
"Catch up"
modelSpace2 catchup.
modelSpace2 getBalanceAt: accId.
modelSpace deposit: 10 at: accId.
modelSpace deposit: 20 at: accId.
modelSpace2 getBalanceAt: accId.
recentEventVersions := modelSpace2 eventVersionsReversedFromLast: 10.
"Time travel"
modelSpace2 goTo: recentEventVersions last.
modelSpace2 getBalanceAt: accId.
modelSpace2 goTo: recentEventVersions first.
modelSpace2 getBalanceAt: accId.
modelSpace2 goTo: recentEventVersions third.
modelSpace2 getBalanceAt: accId.
"EventBridge (notifications)"
bankMailBridge := HtBankAccountMailBridge spaceId: spaceId.
bankMailBridge catchup.
modelSpace putModelOf: HtBankAccount id: '00002' withArguments: {'name'->'Masashi Umezawa'}.
modelSpace deposit: 10000000 at: '00002'.
modelSpace transfer: 2000 from: '00002' to: accId.
"EventBridge (mutation events)"
auditorEventBridge := HsModelEventBridge spaceId: spaceId.
auditorEventBridge eventAnnouncedDo: [:ann | | event |
event := ann event.
Transcript cr; show: ('##{1} typeName:{2} arguments:{3}' format: { event targetId. event typeName. event arguments })
].
auditorEventBridge catchup.
modelSpace deposit: 30 at: accId.
modelSpace withdraw: 40 at: accId.
modelSpace transfer: 5000 from: '00002' to: accId.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment