Skip to content

Commit fc9840a

Browse files
committed
feat: add dynamic module registration
1 parent c78013e commit fc9840a

File tree

12 files changed

+402
-314
lines changed

12 files changed

+402
-314
lines changed

README.md

Lines changed: 7 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,13 @@
1-
# Formance Ledger
1+
<!-- Code generated by gomarkdoc. DO NOT EDIT -->
22

3-
Formance Ledger (fka numary) is a programmable financial ledger that provides a foundation for money-moving applications. The ledger provides atomic multi-postings transactions and is programmable in [Numscript](doc:machine-instructions), a built-in language dedicated to money movements. It can be used either as a standalone micro-service or as part of the greater Formance Stack, and will shine for apps that require a lot of custom, money-moving code, e.g:
3+
# ledger
44

5-
- E-commerce with complex payments flows, payments splitting, such as marketplaces
6-
- Company-issued currencies systems, e.g. Twitch Bits
7-
- In-game currencies, inventories and trading systems, e.g. Fortnite V-Bucks
8-
- Payment gateways using non-standard assets, e.g. learning credits
9-
- Local currencies and complementary finance
5+
```go
6+
import "github.com/formancehq/ledger"
7+
```
108

11-
Formance Ledger works as a standalone binary, the latest of which can be downloaded from the [releases page](https://github.com/formancehq/ledger/releases). You can move the binary to any executable path, such as to `/usr/local/bin`. Installations using brew, apt, yum or docker are also [available](https://docs.formance.com/docs/installation-1).
9+
## Index
1210

13-
## Documentation
1411

15-
You can find the complete Numary documentation at [docs.formance.com](https://docs.formance.com)
1612

17-
## Community
18-
19-
If you need help, want to show us what you built or just hang out and chat about ledgers you are more than welcome on our [Slack](https://bit.ly/formance-slack) - looking forward to see you there!
20-
21-
## Contributing
22-
23-
See [CONTRIBUTING.md](./CONTRIBUTING.md)
13+
Generated by [gomarkdoc](<https://github.com/princjef/gomarkdoc>)

cmd/config.go

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,24 @@ import (
66
"github.com/spf13/viper"
77
)
88

9-
func LoadConfig[V any](cmd *cobra.Command) (*V, error){
9+
func LoadConfig[V any](cmd *cobra.Command) (*V, error) {
10+
var cfg V
11+
if err := MapConfig(cmd, &cfg); err != nil {
12+
return nil, err
13+
}
14+
15+
return &cfg, nil
16+
}
17+
18+
func MapConfig(cmd *cobra.Command, cfg any) error {
1019
v := viper.New()
1120
if err := v.BindPFlags(cmd.Flags()); err != nil {
12-
return nil, fmt.Errorf("binding flags: %w", err)
21+
return fmt.Errorf("binding flags: %w", err)
1322
}
1423

15-
var cfg V
16-
if err := v.Unmarshal(&cfg); err != nil {
17-
return nil, fmt.Errorf("unmarshalling config: %w", err)
24+
if err := v.Unmarshal(cfg); err != nil {
25+
return fmt.Errorf("unmarshalling config: %w", err)
1826
}
1927

20-
return &cfg, nil
28+
return nil
2129
}

cmd/serve.go

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,6 @@ import (
3838
)
3939

4040
type ServeConfig struct {
41-
WorkerConfiguration `mapstructure:",squash"`
42-
4341
Bind string `mapstructure:"bind"`
4442
BallastSizeInBytes uint `mapstructure:"ballast-size"`
4543
NumscriptCacheMaxCount uint `mapstructure:"numscript-cache-max-count"`
@@ -150,10 +148,13 @@ func NewServeCommand() *cobra.Command {
150148
}
151149

152150
if cfg.WorkerEnabled {
153-
options = append(options, worker.NewFXModule(worker.ModuleConfig{
154-
Schedule: cfg.HashLogsBlockCRONSpec,
155-
MaxBlockSize: cfg.HashLogsBlockMaxSize,
156-
}))
151+
workerModule, err := worker.NewFXModule(func(v any) error {
152+
return MapConfig(cmd, v)
153+
})
154+
if err != nil {
155+
return fmt.Errorf("creating worker module: %w", err)
156+
}
157+
options = append(options, workerModule)
157158
}
158159

159160
return service.New(cmd.OutOrStdout(), options...).Run(cmd)

cmd/worker.go

Lines changed: 32 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -11,21 +11,37 @@ import (
1111
"github.com/formancehq/ledger/internal/worker"
1212
"github.com/spf13/cobra"
1313
"go.uber.org/fx"
14+
"reflect"
15+
"strconv"
1416
)
1517

16-
const (
17-
WorkerAsyncBlockHasherMaxBlockSizeFlag = "worker-async-block-hasher-max-block-size"
18-
WorkerAsyncBlockHasherScheduleFlag = "worker-async-block-hasher-schedule"
19-
)
18+
func addWorkerFlags(cmd *cobra.Command) {
19+
for _, runnerFactory := range worker.AllRunnerFactories() {
20+
typeOfRunnerFactory := reflect.TypeOf(runnerFactory)
21+
method, _ := typeOfRunnerFactory.MethodByName("CreateRunner")
22+
configType := method.Type.In(1)
2023

21-
type WorkerConfiguration struct {
22-
HashLogsBlockMaxSize int `mapstructure:"worker-async-block-hasher-max-block-size"`
23-
HashLogsBlockCRONSpec string `mapstructure:"worker-async-block-hasher-schedule"`
24-
}
24+
for i := 0; i < configType.NumField(); i++ {
25+
field := configType.Field(i)
26+
fieldTag := field.Tag
27+
flag := field.Tag.Get("mapstructure")
28+
description := fieldTag.Get("description")
29+
defaultValue := fieldTag.Get("default")
2530

26-
func addWorkerFlags(cmd *cobra.Command) {
27-
cmd.Flags().Int(WorkerAsyncBlockHasherMaxBlockSizeFlag, 1000, "Max block size")
28-
cmd.Flags().String(WorkerAsyncBlockHasherScheduleFlag, "0 * * * * *", "Schedule")
31+
switch field.Type.Kind() {
32+
case reflect.Int, reflect.Int64, reflect.Int32, reflect.Int16, reflect.Int8:
33+
defaultValue, err := strconv.ParseInt(defaultValue, 10, 64)
34+
if err != nil {
35+
panic(err)
36+
}
37+
cmd.Flags().Int(flag, int(defaultValue), description)
38+
case reflect.String:
39+
cmd.Flags().String(flag, defaultValue, description)
40+
default:
41+
panic(fmt.Sprintf("cannot config flag %s as type %T is not handled", flag, field.Type))
42+
}
43+
}
44+
}
2945
}
3046

3147
func NewWorkerCommand() *cobra.Command {
@@ -38,9 +54,11 @@ func NewWorkerCommand() *cobra.Command {
3854
return err
3955
}
4056

41-
cfg, err := LoadConfig[WorkerConfiguration](cmd)
57+
workerModule, err := worker.NewFXModule(func(v any) error {
58+
return MapConfig(cmd, v)
59+
})
4260
if err != nil {
43-
return fmt.Errorf("loading config: %w", err)
61+
return fmt.Errorf("creating worker module: %w", err)
4462
}
4563

4664
return service.New(cmd.OutOrStdout(),
@@ -50,10 +68,7 @@ func NewWorkerCommand() *cobra.Command {
5068
otlpmetrics.FXModuleFromFlags(cmd),
5169
bunconnect.Module(*connectionOptions, service.IsDebug(cmd)),
5270
storage.NewFXModule(storage.ModuleConfig{}),
53-
worker.NewFXModule(worker.ModuleConfig{
54-
MaxBlockSize: cfg.HashLogsBlockMaxSize,
55-
Schedule: cfg.HashLogsBlockCRONSpec,
56-
}),
71+
workerModule,
5772
).Run(cmd)
5873
},
5974
}

go.mod

Lines changed: 41 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ require (
1515
github.com/bluele/gcache v0.0.2
1616
github.com/dop251/goja v0.0.0-20241009100908-5f46f2705ca3
1717
github.com/formancehq/ledger/pkg/client v0.0.0-00010101000000-000000000000
18-
github.com/go-chi/chi/v5 v5.2.1
18+
github.com/go-chi/chi/v5 v5.2.2
1919
github.com/go-chi/cors v1.2.1
2020
github.com/google/go-cmp v0.7.0
2121
github.com/google/uuid v1.6.0
@@ -34,30 +34,32 @@ require (
3434
github.com/spf13/pflag v1.0.6
3535
github.com/stoewer/go-strcase v1.3.0
3636
github.com/stretchr/testify v1.10.0
37-
github.com/uptrace/bun v1.2.13
38-
github.com/uptrace/bun/dialect/pgdialect v1.2.13
39-
github.com/uptrace/bun/extra/bundebug v1.2.12
37+
github.com/uptrace/bun v1.2.14
38+
github.com/uptrace/bun/dialect/pgdialect v1.2.14
39+
github.com/uptrace/bun/extra/bundebug v1.2.14
4040
github.com/xeipuuv/gojsonschema v1.2.0
4141
github.com/xo/dburl v0.23.8
42-
go.opentelemetry.io/otel v1.36.0
43-
go.opentelemetry.io/otel/metric v1.36.0
44-
go.opentelemetry.io/otel/sdk/metric v1.36.0
45-
go.opentelemetry.io/otel/trace v1.36.0
42+
go.opentelemetry.io/otel v1.37.0
43+
go.opentelemetry.io/otel/metric v1.37.0
44+
go.opentelemetry.io/otel/sdk/metric v1.37.0
45+
go.opentelemetry.io/otel/trace v1.37.0
4646
go.uber.org/fx v1.24.0
4747
go.uber.org/mock v0.5.2
4848
golang.org/x/oauth2 v0.30.0
4949
golang.org/x/sync v0.15.0
5050
)
5151

5252
require (
53-
github.com/formancehq/go-libs/v3 v3.0.0-20250610201819-3bfa67aab0e2
53+
github.com/formancehq/go-libs/v3 v3.0.0-20250710143255-4481f63e09c3
5454
github.com/iancoleman/strcase v0.3.0
5555
github.com/robfig/cron/v3 v3.0.1
5656
github.com/spf13/viper v1.20.1
5757
gopkg.in/yaml.v3 v3.0.1
5858
)
5959

6060
require (
61+
github.com/ThreeDotsLabs/watermill-aws v1.0.0 // indirect
62+
github.com/aws/aws-sdk-go-v2/service/sqs v1.38.8 // indirect
6163
github.com/cenkalti/backoff/v5 v5.0.2 // indirect
6264
github.com/fsnotify/fsnotify v1.9.0 // indirect
6365
github.com/google/go-tpm v0.9.5 // indirect
@@ -87,20 +89,20 @@ require (
8789
github.com/ajg/form v1.5.1 // indirect
8890
github.com/antlr4-go/antlr/v4 v4.13.1 // indirect
8991
github.com/aws/aws-msk-iam-sasl-signer-go v1.0.4 // indirect
90-
github.com/aws/aws-sdk-go-v2 v1.36.4 // indirect
91-
github.com/aws/aws-sdk-go-v2/config v1.29.16 // indirect
92-
github.com/aws/aws-sdk-go-v2/credentials v1.17.69 // indirect
93-
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.31 // indirect
94-
github.com/aws/aws-sdk-go-v2/feature/rds/auth v1.5.12 // indirect
95-
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.35 // indirect
96-
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.35 // indirect
92+
github.com/aws/aws-sdk-go-v2 v1.36.5 // indirect
93+
github.com/aws/aws-sdk-go-v2/config v1.29.17 // indirect
94+
github.com/aws/aws-sdk-go-v2/credentials v1.17.70 // indirect
95+
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.32 // indirect
96+
github.com/aws/aws-sdk-go-v2/feature/rds/auth v1.5.13 // indirect
97+
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.36 // indirect
98+
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.36 // indirect
9799
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 // indirect
98-
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.3 // indirect
99-
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.16 // indirect
100-
github.com/aws/aws-sdk-go-v2/service/sso v1.25.4 // indirect
101-
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.2 // indirect
102-
github.com/aws/aws-sdk-go-v2/service/sts v1.33.21 // indirect
103-
github.com/aws/smithy-go v1.22.3 // indirect
100+
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.4 // indirect
101+
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.17 // indirect
102+
github.com/aws/aws-sdk-go-v2/service/sso v1.25.5 // indirect
103+
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.3 // indirect
104+
github.com/aws/aws-sdk-go-v2/service/sts v1.34.0 // indirect
105+
github.com/aws/smithy-go v1.22.4 // indirect
104106
github.com/bahlo/generic-list-go v0.2.0 // indirect
105107
github.com/buger/jsonparser v1.1.1 // indirect
106108
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
@@ -136,11 +138,11 @@ require (
136138
github.com/gorilla/mux v1.8.1 // indirect
137139
github.com/gorilla/schema v1.4.1 // indirect
138140
github.com/gorilla/securecookie v1.1.2 // indirect
139-
github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.3 // indirect
141+
github.com/grpc-ecosystem/grpc-gateway/v2 v2.27.1 // indirect
140142
github.com/hashicorp/errwrap v1.1.0 // indirect
141143
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
142144
github.com/hashicorp/go-multierror v1.1.1 // indirect
143-
github.com/hashicorp/go-retryablehttp v0.7.7 // indirect
145+
github.com/hashicorp/go-retryablehttp v0.7.8 // indirect
144146
github.com/hashicorp/go-uuid v1.0.3 // indirect
145147
github.com/inconshreveable/mousetrap v1.1.0 // indirect
146148
github.com/jackc/pgpassfile v1.0.0 // indirect
@@ -164,7 +166,7 @@ require (
164166
github.com/muhlemmer/gu v0.3.1 // indirect
165167
github.com/muhlemmer/httpforwarded v0.1.0 // indirect
166168
github.com/nats-io/jwt/v2 v2.7.4 // indirect
167-
github.com/nats-io/nats-server/v2 v2.11.4 // indirect
169+
github.com/nats-io/nats-server/v2 v2.11.5 // indirect
168170
github.com/nats-io/nkeys v0.4.11 // indirect
169171
github.com/nats-io/nuid v1.0.1 // indirect
170172
github.com/oklog/ulid v1.3.1 // indirect
@@ -184,7 +186,7 @@ require (
184186
github.com/tklauser/go-sysconf v0.3.15 // indirect
185187
github.com/tklauser/numcpus v0.10.0 // indirect
186188
github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc // indirect
187-
github.com/uptrace/bun/extra/bunotel v1.2.13 // indirect
189+
github.com/uptrace/bun/extra/bunotel v1.2.14 // indirect
188190
github.com/uptrace/opentelemetry-go-extra/otellogrus v0.3.2 // indirect
189191
github.com/uptrace/opentelemetry-go-extra/otelsql v0.3.2 // indirect
190192
github.com/uptrace/opentelemetry-go-extra/otelutil v0.3.2 // indirect
@@ -198,19 +200,19 @@ require (
198200
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
199201
github.com/yusufpapurcu/wmi v1.2.4 // indirect
200202
github.com/zitadel/oidc/v2 v2.12.2 // indirect
201-
go.opentelemetry.io/contrib/instrumentation/host v0.61.0 // indirect
202-
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 // indirect
203-
go.opentelemetry.io/contrib/instrumentation/runtime v0.61.0 // indirect
204-
go.opentelemetry.io/contrib/propagators/b3 v1.36.0 // indirect
205-
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.36.0 // indirect
206-
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.36.0 // indirect
207-
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.36.0 // indirect
208-
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.36.0 // indirect
209-
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.36.0 // indirect
210-
go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.36.0 // indirect
211-
go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.36.0 // indirect
203+
go.opentelemetry.io/contrib/instrumentation/host v0.62.0 // indirect
204+
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.62.0 // indirect
205+
go.opentelemetry.io/contrib/instrumentation/runtime v0.62.0 // indirect
206+
go.opentelemetry.io/contrib/propagators/b3 v1.37.0 // indirect
207+
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.37.0 // indirect
208+
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.37.0 // indirect
209+
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.37.0 // indirect
210+
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.37.0 // indirect
211+
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.37.0 // indirect
212+
go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.37.0 // indirect
213+
go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.37.0 // indirect
212214
go.opentelemetry.io/otel/log v0.12.2 // indirect
213-
go.opentelemetry.io/otel/sdk v1.36.0 // indirect
215+
go.opentelemetry.io/otel/sdk v1.37.0 // indirect
214216
go.opentelemetry.io/proto/otlp v1.7.0 // indirect
215217
go.uber.org/dig v1.19.0 // indirect
216218
go.uber.org/multierr v1.11.0 // indirect
@@ -220,7 +222,7 @@ require (
220222
golang.org/x/net v0.41.0 // indirect
221223
golang.org/x/sys v0.33.0 // indirect
222224
golang.org/x/text v0.26.0 // indirect
223-
golang.org/x/time v0.11.0 // indirect
225+
golang.org/x/time v0.12.0 // indirect
224226
golang.org/x/tools v0.34.0 // indirect
225227
google.golang.org/genproto/googleapis/api v0.0.0-20250603155806-513f23925822 // indirect
226228
google.golang.org/genproto/googleapis/rpc v0.0.0-20250603155806-513f23925822 // indirect

0 commit comments

Comments
 (0)