Skip to content

Instantly share code, notes, and snippets.

@OnurGumus
Created April 30, 2023 08:32
Show Gist options
  • Save OnurGumus/885c0822ac9a8af2d6fb3123b3c6fcf0 to your computer and use it in GitHub Desktop.
Save OnurGumus/885c0822ac9a8af2d6fb3123b3c6fcf0 to your computer and use it in GitHub Desktop.
custom thoth decoder
module Command.Serialization
open Command
open System
open Akkling
open Akkling.Persistence
open Akka.Cluster.Tools.PublishSubscribe
open Akka
open Akka.Cluster.Sharding
open Akkling.Cluster.Sharding
open Akka.Actor
open Akka.Serialization
open System.IO
//open Newtonsoft.Json
open System.Text
open NodaTime.Serialization.SystemTextJson
open System.Text.Json.Serialization
open NodaTime
open Thoth.Json.Net
open System.Runtime.Serialization
open Common
open Command.Domain
open Serilog
module DefaultEncode =
let instant (instant : Instant) =
Encode.datetime (instant.ToDateTimeUtc() )
module DefeaultDecode =
let instant : Decoder<Instant> = Decode.datetimeUtc |> Decode.map(Instant.FromDateTimeUtc)
let extraThoth =
Extra.empty
|> Extra.withInt64
|> Extra.withCustom (DefaultEncode.instant) DefeaultDecode.instant
module Decode =
let defaultEventDecode = Decode.Auto.generateDecoder<User.Event>(extra = extraThoth)
let eventDetails : Decoder<User.Event> =
fun path value ->
let decoder =
if Decode.Helpers.isString value then
let svalue : string = unbox(value.ToObject(typeof<string>))
if svalue = "LoginSucceeded" then
Decode.succeed (User.Event.LoginSucceeded ("", Some 0))
else
defaultEventDecode
elif Decode.Helpers.isArray value then
Decode.index 0 (Decode.string)
|> Decode.andThen (fun tag ->
match tag with
| "LoginSucceeded" ->
let meta = Decode.index 1 (Decode.string)
Decode.map (fun meta -> User.Event.LoginSucceeded (meta, Some 0)) meta
| _ ->
defaultEventDecode
)
else
defaultEventDecode
decoder path value
let eventEncode = Encode.Auto.generateEncoder<User.Event>(extra = extraThoth)
let extraThoth2 =
extraThoth
|> Extra.withCustom (eventEncode) Decode.eventDetails
let userMessageEncode = Encode.Auto.generateEncoder<Common.Event<User.Event> >(extra = extraThoth2)
let userMessageDecode = Decode.Auto.generateDecoder<Common.Event<User.Event> >(extra = extraThoth2)
let calcMessageEncode = Encode.Auto.generateEncoder<Common.Event<Calculation.Event> >(extra = extraThoth)
let calcMessageDecode = Decode.Auto.generateDecoder<Common.Event<Calculation.Event> >(extra = extraThoth)
type ThothSerializer(system: ExtendedActorSystem) =
inherit SerializerWithStringManifest(system)
override __.Identifier = 1712
override __.ToBinary(o) =
match o with
| :? Common.Event<User.Event> as mesg ->
userMessageEncode mesg
|> Encode.toString 4
|> Encoding.UTF8.GetBytes
| :? Common.Event<Calculation.Event> as mesg ->
calcMessageEncode mesg
|> Encode.toString 4
|> Encoding.UTF8.GetBytes
| e ->
failwithf "shouldn't happen %A" e
override this.Manifest(o: obj): string =
match o with
| :? Common.Event<User.Event> -> "UserMessage"
| :? Common.Event<Calculation.Event> -> "CalculationMessage"
| _ -> o.GetType().FullName
override this.FromBinary(bytes: byte[], manifest: string): obj =
match manifest with
| "UserMessage" ->
Encoding.UTF8.GetString(bytes)
|> Decode.fromString userMessageDecode
|> function
| Ok res -> res
| Error er ->
Log.Fatal("Error deserializing {@Error}", er)
raise(new SerializationException(er))
| "CalculationMessage" ->
Encoding.UTF8.GetString(bytes)
|> Decode.fromString calcMessageDecode
|> function
| Ok res -> res
| Error er ->
Log.Fatal("Error deserializing {@Error}", er)
raise(new SerializationException(er))
| _ -> raise(new SerializationException())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment