Skip to content

Instantly share code, notes, and snippets.

@atsapura
Created September 1, 2023 16:31
Show Gist options
  • Save atsapura/6976f0941e5bffb5c68bc212180d2468 to your computer and use it in GitHub Desktop.
Save atsapura/6976f0941e5bffb5c68bc212180d2468 to your computer and use it in GitHub Desktop.
App Env example with test env
type IAppEnv =
abstract member Now: Instant
abstract member OrderDiffStorage: IOrderDiffStorage
abstract member DomainOrderStorage: IOrderStorage
abstract member OrderEventSender: IOrderEventSender
abstract member CatalogClient: ICatalogClient
abstract member ErpOrderListener: IErpOrderListener
abstract member Config: Config
type AppEnv(diffStorage: IOrderDiffStorage,
domainOrderStorage: IOrderStorage,
orderEventSender: IOrderEventSender,
catalogClient: ICatalogClient,
erpOrderListener: IErpOrderListener,
config) =
member _.Now = currentInstant()
member _.OrderDiffStorage = diffStorage
member _.DomainOrderStorage = domainOrderStorage
member _.OrderEventSender = orderEventSender
member _.Config = config
member _.CatalogClient = catalogClient
member _.ErpOrderListener = erpOrderListener
interface IAppEnv with
member this.Now = this.Now
member this.OrderDiffStorage = this.OrderDiffStorage
member this.DomainOrderStorage = this.DomainOrderStorage
member this.OrderEventSender = this.OrderEventSender
member this.Config = this.Config
member this.CatalogClient = this.CatalogClient
member this.ErpOrderListener = this.ErpOrderListener
type ConfiguredEnv =
inherit AppEnv
new (configuration, logger, httpClientFactory) =
let serviceBusClient = ServiceBusClient(configuration.Infrastructure.ServiceBusConnection)
let blobClient = BlobServiceClient(configuration.Infrastructure.BlobConnection)
let queueClient = QueueClient(configuration.Infrastructure.BlobConnection, AzureQueues.ErpOrders)
let customerDbClient = CustomerDb.clientForConnectionString configuration.Infrastructure.CustomerDbConnection
let orderDiffContainerClient = blobClient.GetBlobContainerClient("erp-order-diffs-test")
let ordersContainer = blobClient.GetBlobContainerClient("erp-orders")
let diffStorage = OrderDiffStorage.Client(orderDiffContainerClient)
let domainOrderStorage = OrderStorage.Client(customerDbClient)
let eventSender = OrderEventSender.Client(serviceBusClient)
let erpOrderListener = ErpOrderListener(queueClient, ordersContainer, logger)
let catalogClient =
CatalogClient(httpClientFactory, catalogSettingOfConfig configuration.Infrastructure)
{ inherit AppEnv(diffStorage, domainOrderStorage, eventSender, catalogClient, erpOrderListener, configuration) }
module MigrationEnvironment =
type FakeEventSender() =
member _.Send events =
async {
return ()
}
interface IOrderEventSender with
member this.Send e = this.Send e
type BlobOrderSaver(blobClient: BlobServiceClient) =
let blobContainer = blobClient.GetBlobContainerClient "domain-orders-test"
let blobName orderId = $"%i{orderId}.json"
member _.SaveOrder order =
async {
let entity = customerOrderToEntity order
let content = JsonConvert.SerializeObject entity |> BinaryData
let! r = blobContainer.UploadBlobAsync(blobName order.ErpOrderId, content) |> Async.AwaitTask
return Ok()
}
member _.GetOrder orderId =
async {
let blobClient = blobContainer.GetBlobClient(blobName orderId)
let! resp = blobClient.DownloadContentAsync() |> Async.AwaitTask
if resp.HasValue then
let content = resp.Value.Content.ToString()
let entity = JsonConvert.DeserializeObject<RootSalesOrderEntity> content
return entity |> customerOrderToDomain |> Some
else return None
}
interface IOrderStorage with
member this.GetOrder id = this.GetOrder id
member this.SaveOrder order = this.SaveOrder order
type MigrationEnv =
inherit AppEnv
new (configuration, logger, httpClientFactory) =
let blobClient = BlobServiceClient(configuration.Infrastructure.BlobConnection)
let queueClient = QueueClient(configuration.Infrastructure.BlobConnection, AzureQueues.ErpOrders)
let orderDiffContainerClient = blobClient.GetBlobContainerClient("erp-order-diffs-test")
let ordersContainer = blobClient.GetBlobContainerClient("erp-orders")
let diffStorage = OrderDiffStorage.Client(orderDiffContainerClient)
let domainOrderStorage = BlobOrderSaver blobClient
let eventSender = FakeEventSender()
let erpOrderListener = ErpOrderListener(queueClient, ordersContainer, logger)
let catalogClient =
CatalogClient(httpClientFactory, catalogSettingOfConfig configuration.Infrastructure)
{ inherit AppEnv(diffStorage, domainOrderStorage, eventSender, catalogClient, erpOrderListener, configuration) }
module TestEnvironment =
let createConsoleLogger<'T>() =
LoggerFactory.Create(fun builder ->
builder.AddSimpleConsole(fun options ->
options.SingleLine <- true
options.IncludeScopes <- true
options.TimestampFormat <- "HH:mm:ss") |> ignore
).CreateLogger<'T>()
type BullshitHttpFactory() =
let nameRegistry = Dictionary<_,_>()
interface IHttpClientFactory with
member this.CreateClient name =
match Dict.tryFind name nameRegistry with
| None ->
let client = new HttpClient()
nameRegistry.Add(name, client)
client
| Some client -> client
type FakeErpOrderListener(erpOrderContainer: BlobContainerClient, logger: ILogger) =
let orderIds =
[|
3312620
3312620
3312619
|] |> Array.map (fun i -> $"%i{i}.json")
let mutable i = 0
member this.GetIncomingOrder() =
task {
do! Async.Sleep (TimeSpan.FromSeconds 10)
if i < orderIds.Length - 1 then
let blobPath = orderIds[i]
i <- i + 1
let blobClient = erpOrderContainer.GetBlobClient blobPath
let! content = blobClient.DownloadContentAsync()
if content.HasValue then
let json = content.Value.Content.ToString()
let orderId = blobPath |> System.IO.Path.GetFileNameWithoutExtension
match tryParse<int> orderId with
| None ->
logger.LogCritical($"Invalid order id %s{orderId}")
return None
| Some orderId ->
let message =
{
IncomingOrder.OrderId = orderId
Order = json
}
return Some message
else
logger.LogError($"No content for blob %s{blobPath}")
return None
else
logger.LogError("No content for azure queue message")
return None
}
interface IErpOrderListener with
member this.GetIncomingOrder() = this.GetIncomingOrder()
type FakeListenerEnv =
inherit AppEnv
new (configuration) =
let logger = createConsoleLogger<FakeListenerEnv>()
let httpClientFactory = BullshitHttpFactory()
let serviceBusClient = ServiceBusClient(configuration.Infrastructure.ServiceBusConnection)
let blobClient = BlobServiceClient(configuration.Infrastructure.BlobConnection)
let customerDbClient = CustomerDb.clientForConnectionString configuration.Infrastructure.CustomerDbConnection
let orderDiffContainerClient = blobClient.GetBlobContainerClient("erp-order-diffs-test")
let ordersContainer = blobClient.GetBlobContainerClient("erp-orders")
let diffStorage = OrderDiffStorage.Client(orderDiffContainerClient)
let domainOrderStorage = OrderStorage.Client(customerDbClient)
let eventSender = OrderEventSender.Client(serviceBusClient)
let erpOrderListener = FakeErpOrderListener(ordersContainer, logger)
let catalogClient =
CatalogClient(httpClientFactory, catalogSettingOfConfig configuration.Infrastructure)
{ inherit AppEnv(diffStorage, domainOrderStorage, eventSender, catalogClient, erpOrderListener, configuration) }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment