Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- open System
- //open Akka.FSharp
- open Akka.FSharp
- let inline (^) f x = f x
- let system = System.create "my-system" (Configuration.load())
- //let sagaActor =
- // spawn system "saga-handler-actor"
- // (fun mailbox ->
- // let rec loop() = actor {
- // let! message = mailbox.Receive()
- // let events = commandHandler message
- // //saga-event-listener
- // //wait
- // //check if events are ok
- // //parent <! Tell
- // return! loop()
- // }
- // loop())
- //let eventHandlerActor =
- // spawn system "command-handler-actor"
- // (fun mailbox ->
- // let rec loop() = actor {
- // let! message = mailbox.Receive()
- // eventHandler message
- // return! loop()
- // }
- // loop())
- //let requestHandlerActor =
- // spawn system "request-handler-actor"
- // (fun mailbox ->
- // let rec loop() = actor {
- // let! message = mailbox.Receive()
- // //sagaActor <! message
- // //create child actor for handle command ::commandHandlerActor::
- // // handle an incoming message
- // return! loop()
- // }
- // loop())
- type Cmd =
- | CreateUser of string
- | RemoveUser of Guid
- type Evt =
- | UserCreated of Guid * string
- | UserRemoved of Guid
- let idGenerator () = Guid.NewGuid()
- let createUser name =
- if not <| String.IsNullOrEmpty name then
- [UserCreated (idGenerator(), name)]
- else
- []
- let commandHandler cmd =
- match cmd with
- | CreateUser name ->
- createUser name
- | RemoveUser id -> []
- let eventHandler evt =
- match evt with
- | CreateUser name -> ()
- | RemoveUser id -> ()
- type Command = unit
- type ForwardCommand = Forward of Command
- type BackwardCommand = Backward of Command
- [<RequireQualifiedAccessAttribute>]
- type SagaState =
- | Empty
- | Fill of ForwardCommand list
- | Forward of Currect: ForwardCommand * Remains: ForwardCommand list * Completed: ForwardCommand list
- | Backward of Currect: BackwardCommand * Remains: BackwardCommand list * Completed: BackwardCommand list * ForwardCompleted: ForwardCommand list * ForwardRemains : ForwardCommand list
- | BackwardAbort of FailCommand: BackwardCommand * Remains: BackwardCommand list * Completed: BackwardCommand list * ForwardCompleted: ForwardCommand list * ForwardRemains : ForwardCommand list
- | ForwardComplete of Completed: ForwardCommand list
- | BackwardComplete of Completed: BackwardCommand list * ForwardCompleted: ForwardCommand list * ForwardRemains : ForwardCommand list
- [<RequireQualifiedAccessAttribute>]
- type SagaEvent =
- | SagaForwardCommandAdded of ForwardCommand
- | Started
- | Forwarded
- | ForwardFailed
- | Backwarded
- | BackwardFailed
- | ForwardDone
- | BackwardDone
- let initSaga = SagaState.Empty
- let forwardToBackward (Forward cmd) = Backward cmd
- let applyEvent state event =
- match state, event with
- | SagaState.Empty, SagaEvent.SagaForwardCommandAdded cmd ->
- SagaState.Fill ^ [cmd]
- | SagaState.Fill cmds, SagaEvent.SagaForwardCommandAdded cmd ->
- SagaState.Fill ^ (cmd :: cmds)
- | SagaState.Fill (c::cs), SagaEvent.Started ->
- SagaState.Forward (c, cs |> List.rev, [])
- | SagaState.Forward (current, next::remains, completed), SagaEvent.Forwarded ->
- SagaState.Forward (next, remains, current::completed)
- | SagaState.Forward (current, [], completed), SagaEvent.Forwarded ->
- SagaState.ForwardComplete (current::completed)
- | SagaState.Forward (current, remains, completed), SagaEvent.ForwardFailed ->
- SagaState.Backward (current |> forwardToBackward, completed |> List.map forwardToBackward, [], completed, current::remains)
- | SagaState.Backward (current, next::remains, completed, forwardCompleted, forwardRemains), SagaEvent.Backwarded ->
- SagaState.Backward (next, remains, current::completed, forwardCompleted, forwardRemains)
- | SagaState.Backward (current, [], completed, forwardCompleted, forwardRemains), SagaEvent.Backwarded ->
- SagaState.BackwardComplete (current::completed, forwardCompleted, forwardRemains)
- | SagaState.Backward (current, remains, completed, forwardCompleted, forwardRemains), SagaEvent.BackwardFailed ->
- SagaState.BackwardAbort (current, remains, completed, forwardCompleted, forwardRemains)
- | state, event -> failwith (sprintf "Wrong state %A %A" state event)
- let playEvents state events = events |> List.fold applyEvent state
- type NoneEmptyString = private NoneEmptyString of string
- module NoneEmptyString =
- let create str =
- if str = "" then
- failwith "Must be none-empty"
- else
- NoneEmptyString str
- type Ticket = {
- Owner: NoneEmptyString
- QRCode: NoneEmptyString
- EventName: NoneEmptyString
- }
- type Event = {
- Name: NoneEmptyString
- StartDate: DateTime
- EndDate: DateTime
- TotalTicketCound: uint32
- SoldTickets: Ticket list
- }
- type PeopleCount = uint32
- type EventState =
- | SellTicketEvent of Event
- | RunEvent of Event * PeopleCount
- type EventCommand =
- | AddTicket of Owner: NoneEmptyString
- | RemoveTicket of Owner: NoneEmptyString
- | Scan of QRCode: NoneEmptyString
- let private createTicket eventName owner =
- { Owner = owner
- QRCode = NoneEmptyString.create "123"
- EventName = eventName }
- let private addTicket ticket event =
- { event with SoldTickets = ticket::event.SoldTickets }
- let private removeTicket ticket event =
- { event with SoldTickets = event.SoldTickets |> List.filter(fun x -> x <> ticket) }
- let private getTicket pred event =
- event.SoldTickets |> List.tryFind pred
- let addTicketFor user eventState =
- match eventState with
- | SellTicketEvent ({ Name = eventName } as event) ->
- let ticket = createTicket eventName user
- Ok (addTicket ticket event)
- | _ ->
- Error "Wrong state"
- let removeTicketFor owner eventState =
- match eventState with
- | SellTicketEvent event ->
- let ticket = getTicket (fun x -> x.Owner = owner) event
- match ticket with
- | Some t -> Ok (removeTicket t event)
- | None -> Error "Alarm! impossible case"
- | _ ->
- Error "Wrong state"
- let scan qrCode eventState =
- match eventState with
- | RunEvent (event, peopleCount) ->
- if peopleCount > 1000u then
- Error "to many people"
- else
- let ticket = getTicket (fun x -> x.QRCode = qrCode) event
- Ok (Option.isSome ticket)
- | _ -> Error "Wrong state"
- let applyCommand command eventState =
- match eventState, command with
- | SellTicketEvent event, AddTicket owner ->
- let ticket = createTicket event.Name owner
- Ok (true, SellTicketEvent (addTicket ticket event))
- | SellTicketEvent event, RemoveTicket owner ->
- let ticket = getTicket (fun x -> x.Owner = owner) event
- match ticket with
- | Some t -> Ok (true, SellTicketEvent (removeTicket t event))
- | None -> Error "Alarm! impossible case"
- | RunEvent (event, peopleCount), Scan qrCode ->
- if peopleCount > 1000u then
- Error "to many people"
- else
- let ticket = getTicket (fun x -> x.QRCode = qrCode) event
- Ok ((Option.isSome ticket), eventState)
- | _ -> failwith "not ok"
- [<EntryPoint>]
- let main argv =
- //let testSaga =
- // [SagaEvent.SagaForwardCommandAdded ^ Forward ()
- // SagaEvent.SagaForwardCommandAdded ^ Forward ()
- // SagaEvent.Started
- // SagaEvent.Forwarded
- // SagaEvent.ForwardFailed
- // SagaEvent.Backwarded
- // SagaEvent.BackwardFailed]
- // |> playEvents initSaga
- //printf "%A" testSaga
- let sellTicketEvent =
- SellTicketEvent {
- Name = NoneEmptyString.create "F#"
- StartDate = DateTime.UtcNow
- EndDate = DateTime.UtcNow
- TotalTicketCound = 10u
- SoldTickets = []
- }
- let addTicket = applyCommand (EventCommand.AddTicket (NoneEmptyString.create "me")) sellTicketEvent
- printf "%A" addTicket
- Console.ReadKey() |> ignore
- 0
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement