Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: Tidy Argu processing #135

Merged
merged 1 commit into from
Dec 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ The `Unreleased` section name is replaced by the expected version of next releas
### Changed

- Target `Equinox` v `4.0.0-rc.14.5`, `Propulsion` v `3.0.0-rc.9.11`, `FsCodec` v `3.0.0-rc.14.1` [#131](https://github.com/jet/dotnet-templates/pull/131)
- Target `Argu` v `6.0.14` [#135](https://github.com/jet/dotnet-templates/pull/135)

### Removed

Expand Down
5 changes: 2 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -353,10 +353,9 @@ let main argv =
try let args = Args.parse EnvVar.tryGet argv
try Log.Logger <- LoggerConfiguration().Configure(verbose=args.Verbose).CreateLogger()
try run args |> Async.RunSynchronously; 0
with e when not (e :? MissingArg) -> Log.Fatal(e, "Exiting"); 2
with e when not (e :? System.Threading.Tasks.TaskCanceledException) -> Log.Fatal(e, "Exiting"); 2
finally Log.CloseAndFlush()
with MissingArg msg -> eprintfn "%s" msg; 1
| :? Argu.ArguParseException as e -> eprintfn "%s" e.Message; 1
with :? Argu.ArguParseException as e -> eprintfn "%s" e.Message; 1
| e -> eprintf "Exception %s" e.Message; 1
```

Expand Down
2 changes: 1 addition & 1 deletion equinox-shipping/Watchdog.Lambda/Function.fs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ open System
type Configuration(appName, ?tryGet) =
let envVarTryGet = Environment.GetEnvironmentVariable >> Option.ofObj
let tryGet = defaultArg tryGet envVarTryGet
let get key = match tryGet key with Some value -> value | None -> failwithf "Missing Argument/Environment Variable %s" key
let get key = match tryGet key with Some value -> value | None -> failwithf $"Missing Argument/Environment Variable %s{key}"

member _.DynamoRegion = tryGet Propulsion.DynamoStore.Lambda.Args.Dynamo.REGION
member _.DynamoServiceUrl = get Propulsion.DynamoStore.Lambda.Args.Dynamo.SERVICE_URL
Expand Down
39 changes: 18 additions & 21 deletions equinox-shipping/Watchdog/Args.fs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,6 @@ module Args
open System
open FSharp.Control

exception MissingArg of message: string with override this.Message = this.message
let missingArg msg = raise (MissingArg msg)

let [<Literal>] REGION = "EQUINOX_DYNAMO_REGION"
let [<Literal>] SERVICE_URL = "EQUINOX_DYNAMO_SERVICE_URL"
let [<Literal>] ACCESS_KEY = "EQUINOX_DYNAMO_ACCESS_KEY_ID"
Expand All @@ -16,20 +13,20 @@ let [<Literal>] INDEX_TABLE = "EQUINOX_DYNAMO_TABLE_INDEX"

type Configuration(tryGet: string -> string option) =

let get key = match tryGet key with Some value -> value | None -> failwith $"Missing Argument/Environment Variable %s{key}"
member val tryGet = tryGet
member _.get key = match tryGet key with Some value -> value | None -> missingArg $"Missing Argument/Environment Variable %s{key}"

member x.CosmosConnection = x.get "EQUINOX_COSMOS_CONNECTION"
member x.CosmosDatabase = x.get "EQUINOX_COSMOS_DATABASE"
member x.CosmosContainer = x.get "EQUINOX_COSMOS_CONTAINER"
member _.CosmosConnection = get "EQUINOX_COSMOS_CONNECTION"
member _.CosmosDatabase = get "EQUINOX_COSMOS_DATABASE"
member _.CosmosContainer = get "EQUINOX_COSMOS_CONTAINER"

member x.DynamoServiceUrl = x.get SERVICE_URL
member x.DynamoAccessKey = x.get ACCESS_KEY
member x.DynamoSecretKey = x.get SECRET_KEY
member x.DynamoTable = x.get TABLE
member x.DynamoRegion = x.tryGet REGION
member _.DynamoServiceUrl = get SERVICE_URL
member _.DynamoAccessKey = get ACCESS_KEY
member _.DynamoSecretKey = get SECRET_KEY
member _.DynamoTable = get TABLE
member _.DynamoRegion = tryGet REGION

member x.EventStoreConnection = x.get "EQUINOX_ES_CONNECTION"
member _.EventStoreConnection = get "EQUINOX_ES_CONNECTION"
member _.MaybeEventStoreConnection = tryGet "EQUINOX_ES_CONNECTION"
member _.MaybeEventStoreCredentials = tryGet "EQUINOX_ES_CREDENTIALS"

Expand All @@ -50,7 +47,7 @@ module Cosmos =
| [<AltCommandLine "-rt">] RetriesWaitTime of float
interface IArgParserTemplate with
member p.Usage = p |> function
| Verbose _ -> "request verbose logging."
| Verbose -> "request verbose logging."
| ConnectionMode _ -> "override the connection mode. Default: Direct."
| Connection _ -> "specify a connection string for a Cosmos account. (optional if environment variable EQUINOX_COSMOS_CONNECTION specified)"
| Database _ -> "specify a database name for Cosmos store. (optional if environment variable EQUINOX_COSMOS_DATABASE specified)"
Expand All @@ -60,15 +57,15 @@ module Cosmos =
| RetriesWaitTime _ -> "specify max wait-time for retry when being throttled by Cosmos in seconds (default: 5)"

type Arguments(c: Configuration, p: ParseResults<Parameters>) =
let connection = p.TryGetResult Connection |> Option.defaultWith (fun () -> c.CosmosConnection)
let connection = p.GetResult(Connection, fun () -> c.CosmosConnection)
let discovery = Equinox.CosmosStore.Discovery.ConnectionString connection
let mode = p.TryGetResult ConnectionMode
let timeout = p.GetResult(Timeout, 5.) |> TimeSpan.FromSeconds
let retries = p.GetResult(Retries, 1)
let maxRetryWaitTime = p.GetResult(RetriesWaitTime, 5.) |> TimeSpan.FromSeconds
let connector = Equinox.CosmosStore.CosmosStoreConnector(discovery, timeout, retries, maxRetryWaitTime, ?mode = mode)
let database = p.TryGetResult Database |> Option.defaultWith (fun () -> c.CosmosDatabase)
let container = p.TryGetResult Container |> Option.defaultWith (fun () -> c.CosmosContainer)
let database = p.GetResult(Database, fun () -> c.CosmosDatabase)
let container = p.GetResult(Container, fun () -> c.CosmosContainer)
member val Verbose = p.Contains Verbose
member _.Connect() = connector.ConnectContext(database, container)

Expand Down Expand Up @@ -102,9 +99,9 @@ module Dynamo =
| Some systemName ->
Choice1Of2 systemName
| None ->
let serviceUrl = p.TryGetResult ServiceUrl |> Option.defaultWith (fun () -> c.DynamoServiceUrl)
let accessKey = p.TryGetResult AccessKey |> Option.defaultWith (fun () -> c.DynamoAccessKey)
let secretKey = p.TryGetResult SecretKey |> Option.defaultWith (fun () -> c.DynamoSecretKey)
let serviceUrl = p.GetResult(ServiceUrl, fun () -> c.DynamoServiceUrl)
let accessKey = p.GetResult(AccessKey, fun () -> c.DynamoAccessKey)
let secretKey = p.GetResult(SecretKey, fun () -> c.DynamoSecretKey)
Choice2Of2 (serviceUrl, accessKey, secretKey)
let connector = let timeout = p.GetResult(RetriesTimeoutS, 5.) |> TimeSpan.FromSeconds
let retries = p.GetResult(Retries, 1)
Expand All @@ -113,7 +110,7 @@ module Dynamo =
Equinox.DynamoStore.DynamoStoreConnector(systemName, timeout, retries)
| Choice2Of2 (serviceUrl, accessKey, secretKey) ->
Equinox.DynamoStore.DynamoStoreConnector(serviceUrl, accessKey, secretKey, timeout, retries)
let table = p.TryGetResult Table |> Option.defaultWith (fun () -> c.DynamoTable)
let table = p.GetResult(Table, fun () -> c.DynamoTable)
member _.Connect() = connector.CreateClient().CreateContext("Main", table)

type [<RequireQualifiedAccess; NoComparison; NoEquality>]
Expand Down
19 changes: 9 additions & 10 deletions equinox-shipping/Watchdog/Program.fs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ open System
module Args =

open Argu
[<NoEquality; NoComparison>]
[<NoEquality; NoComparison; RequireSubcommand>]
type Parameters =
| [<AltCommandLine "-V"; Unique>] Verbose
| [<AltCommandLine "-g"; Mandatory>] ProcessorName of string
Expand All @@ -17,9 +17,9 @@ module Args =
| [<AltCommandLine "-i"; Unique>] IdleDelayMs of int
| [<AltCommandLine "-W"; Unique>] WakeForResults

| [<CliPrefix(CliPrefix.None); Unique; Last>] Cosmos of ParseResults<SourceArgs.Cosmos.Parameters>
| [<CliPrefix(CliPrefix.None); Unique; Last>] Dynamo of ParseResults<SourceArgs.Dynamo.Parameters>
| [<CliPrefix(CliPrefix.None); Unique; Last>] Esdb of ParseResults<SourceArgs.Esdb.Parameters>
| [<CliPrefix(CliPrefix.None)>] Cosmos of ParseResults<SourceArgs.Cosmos.Parameters>
| [<CliPrefix(CliPrefix.None)>] Dynamo of ParseResults<SourceArgs.Dynamo.Parameters>
| [<CliPrefix(CliPrefix.None)>] Esdb of ParseResults<SourceArgs.Esdb.Parameters>
interface IArgParserTemplate with
member p.Usage = p |> function
| Verbose -> "request Verbose Logging. Default: off."
Expand All @@ -29,7 +29,7 @@ module Args =
| TimeoutS _ -> "Timeout (in seconds) before Watchdog should step in to process transactions. Default: 10."

| IdleDelayMs _ -> "Idle delay for scheduler. Default 1000ms"
| WakeForResults _ -> "Wake for all results to provide optimal throughput"
| WakeForResults -> "Wake for all results to provide optimal throughput"

| Cosmos _ -> "specify CosmosDB parameters."
| Dynamo _ -> "specify DynamoDB input parameters"
Expand All @@ -55,7 +55,7 @@ module Args =
| Cosmos a -> Choice1Of3 <| SourceArgs.Cosmos.Arguments(c, a)
| Dynamo a -> Choice2Of3 <| SourceArgs.Dynamo.Arguments(c, a)
| Esdb a -> Choice3Of3 <| SourceArgs.Esdb.Arguments(c, a)
| a -> Args.missingArg $"Unexpected Store subcommand %A{a}"
| a -> failwith $"Unexpected Store subcommand %A{a}"
member x.VerboseStore = match x.Store with
| Choice1Of3 s -> s.Verbose
| Choice2Of3 s -> s.Verbose
Expand Down Expand Up @@ -128,8 +128,7 @@ let main argv =
try let args = Args.parse EnvVar.tryGet argv
try Log.Logger <- LoggerConfiguration().Configure(verbose = args.Verbose).CreateLogger()
try run args |> Async.RunSynchronously; 0
with e when not (e :? Args.MissingArg) && not (e :? System.Threading.Tasks.TaskCanceledException) -> Log.Fatal(e, "Exiting"); 2
with e when not (e :? System.Threading.Tasks.TaskCanceledException) -> Log.Fatal(e, "Exiting"); 2
finally Log.CloseAndFlush()
with Args.MissingArg msg -> eprintfn "%s" msg; 1
| :? Argu.ArguParseException as e -> eprintfn "%s" e.Message; 1
| e -> eprintf "Exception %s" e.Message; 1
with :? Argu.ArguParseException as e -> eprintfn $"%s{e.Message}"; 1
| e -> eprintf $"Exception %s{e.Message}"; 1
28 changes: 14 additions & 14 deletions equinox-shipping/Watchdog/SourceArgs.fs
Original file line number Diff line number Diff line change
Expand Up @@ -42,14 +42,14 @@ module Cosmos =
| LagFreqM _ -> "specify frequency (minutes) to dump lag stats. Default: 1"

type Arguments(c: Args.Configuration, p: ParseResults<Parameters>) =
let discovery = p.TryGetResult Connection |> Option.defaultWith (fun () -> c.CosmosConnection) |> Equinox.CosmosStore.Discovery.ConnectionString
let discovery = p.GetResult(Connection, fun () -> c.CosmosConnection) |> Equinox.CosmosStore.Discovery.ConnectionString
let mode = p.TryGetResult ConnectionMode
let timeout = p.GetResult(Timeout, 5.) |> TimeSpan.FromSeconds
let retries = p.GetResult(Retries, 9)
let maxRetryWaitTime = p.GetResult(RetriesWaitTime, 30.) |> TimeSpan.FromSeconds
let connector = Equinox.CosmosStore.CosmosStoreConnector(discovery, timeout, retries, maxRetryWaitTime, ?mode = mode)
let database = p.TryGetResult Database |> Option.defaultWith (fun () -> c.CosmosDatabase)
let containerId = p.TryGetResult Container |> Option.defaultWith (fun () -> c.CosmosContainer)
let database = p.GetResult(Database, fun () -> c.CosmosDatabase)
let containerId = p.GetResult(Container, fun () -> c.CosmosContainer)
let leaseContainerId = p.GetResult(LeaseContainer, containerId + "-aux")
let fromTail = p.Contains FromTail
let maxItems = p.TryGetResult MaxItems
Expand Down Expand Up @@ -99,9 +99,9 @@ module Dynamo =
| Some systemName ->
Choice1Of2 systemName
| None ->
let serviceUrl = p.TryGetResult ServiceUrl |> Option.defaultWith (fun () -> c.DynamoServiceUrl)
let accessKey = p.TryGetResult AccessKey |> Option.defaultWith (fun () -> c.DynamoAccessKey)
let secretKey = p.TryGetResult SecretKey |> Option.defaultWith (fun () -> c.DynamoSecretKey)
let serviceUrl = p.GetResult(ServiceUrl, fun () -> c.DynamoServiceUrl)
let accessKey = p.GetResult(AccessKey, fun () -> c.DynamoAccessKey)
let secretKey = p.GetResult(SecretKey, fun () -> c.DynamoSecretKey)
Choice2Of2 (serviceUrl, accessKey, secretKey)
let connector = let timeout = p.GetResult(RetriesTimeoutS, 60.) |> TimeSpan.FromSeconds
let retries = p.GetResult(Retries, 9)
Expand All @@ -110,9 +110,9 @@ module Dynamo =
Equinox.DynamoStore.DynamoStoreConnector(systemName, timeout, retries)
| Choice2Of2 (serviceUrl, accessKey, secretKey) ->
Equinox.DynamoStore.DynamoStoreConnector(serviceUrl, accessKey, secretKey, timeout, retries)
let table = p.TryGetResult Table |> Option.defaultWith (fun () -> c.DynamoTable)
let table = p.GetResult(Table, fun () -> c.DynamoTable)
let indexSuffix = p.GetResult(IndexSuffix, "-index")
let indexTable = p.TryGetResult IndexTable |> Option.orElseWith (fun () -> c.DynamoIndexTable) |> Option.defaultWith (fun () -> table + indexSuffix)
let indexTable = p.GetResult(IndexTable, fun () -> defaultArg c.DynamoIndexTable (table + indexSuffix))
let fromTail = p.Contains FromTail
let tailSleepInterval = TimeSpan.FromMilliseconds 500.
let batchSizeCutoff = p.GetResult(MaxItems, 100)
Expand Down Expand Up @@ -142,9 +142,9 @@ module Esdb =
Propulsion.Feed.ReaderCheckpoint.CosmosStore.create Store.Metrics.log (consumerGroup, checkpointInterval) (context, cache)
| Store.Config.Dynamo (context, cache) ->
Propulsion.Feed.ReaderCheckpoint.DynamoStore.create Store.Metrics.log (consumerGroup, checkpointInterval) (context, cache)
| Store.Config.Memory _ | Store.Config.Esdb _ -> Args.missingArg "Unexpected store type"
| Store.Config.Memory _ | Store.Config.Esdb _ -> failwith "Unexpected store type"

type [<NoEquality; NoComparison>] Parameters =
type [<NoEquality; NoComparison; RequireSubcommand>] Parameters =
| [<AltCommandLine "-V">] Verbose
| [<AltCommandLine "-c">] Connection of string
| [<AltCommandLine "-p"; Unique>] Credentials of string
Expand All @@ -154,8 +154,8 @@ module Esdb =
| [<AltCommandLine "-b"; Unique>] MaxItems of int
| [<AltCommandLine "-Z"; Unique>] FromTail

| [<CliPrefix(CliPrefix.None); Unique(*ExactlyOnce is not supported*); Last>] Cosmos of ParseResults<Args.Cosmos.Parameters>
| [<CliPrefix(CliPrefix.None); Unique(*ExactlyOnce is not supported*); Last>] Dynamo of ParseResults<Args.Dynamo.Parameters>
| [<CliPrefix(CliPrefix.None)>] Cosmos of ParseResults<Args.Cosmos.Parameters>
| [<CliPrefix(CliPrefix.None)>] Dynamo of ParseResults<Args.Dynamo.Parameters>
interface IArgParserTemplate with
member p.Usage = p |> function
| Verbose -> "Include low level Store logging."
Expand All @@ -174,7 +174,7 @@ module Esdb =
let startFromTail = p.Contains FromTail
let maxItems = p.GetResult(MaxItems, 100)
let tailSleepInterval = TimeSpan.FromSeconds 0.5
let connectionStringLoggable = p.TryGetResult Connection |> Option.defaultWith (fun () -> c.EventStoreConnection)
let connectionStringLoggable = p.GetResult(Connection, fun () -> c.EventStoreConnection)
let credentials = p.TryGetResult Credentials |> Option.orElseWith (fun () -> c.MaybeEventStoreCredentials)
let discovery = match credentials with Some x -> String.Join(";", connectionStringLoggable, x) | None -> connectionStringLoggable
|> Equinox.EventStoreDb.Discovery.ConnectionString
Expand All @@ -193,7 +193,7 @@ module Esdb =
match p.GetSubCommand() with
| Cosmos cosmos -> Args.TargetStoreArgs.Cosmos (Args.Cosmos.Arguments(c, cosmos))
| Dynamo dynamo -> Args.TargetStoreArgs.Dynamo (Args.Dynamo.Arguments(c, dynamo))
| _ -> Args.missingArg "Must specify `cosmos` or `dynamo` target store when source is `esdb`"
| _ -> p.Raise "Must specify `cosmos` or `dynamo` target store when source is `esdb`"

member _.MonitoringParams(log: ILogger) =
log.Information("EventStoreSource MaxItems {maxItems} ", maxItems)
Expand Down
2 changes: 1 addition & 1 deletion equinox-shipping/Watchdog/Watchdog.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="Argu" Version="6.1.1" />
<PackageReference Include="Argu" Version="6.1.4" />
<PackageReference Include="Propulsion.CosmosStore" Version="3.0.0-rc.9.11" />
<PackageReference Include="Propulsion.DynamoStore" Version="3.0.0-rc.9.11" />
<PackageReference Include="Propulsion.EventStoreDb" Version="3.0.0-rc.9.11" />
Expand Down
Loading