diff --git a/CHANGELOG.md b/CHANGELOG.md index 24a87669..7be6ac62 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,39 @@ +## [1.10.0-beta.2](https://github.com/LerianStudio/midaz/compare/v1.10.0-beta.1...v1.10.0-beta.2) (2024-09-19) + + +### Features + +* add grpc port to midaz on 50051 to run togheter with fiber :sparkles: ([a9c4551](https://github.com/LerianStudio/midaz/commit/a9c45514be5239593b9a26d1838d140c372d3836)) +* add midaz version :sparkles: ([27c56aa](https://github.com/LerianStudio/midaz/commit/27c56aac4aaeffbdd6093a69dbc80e84ea9331ee)) +* add proto url, address :sparkles: ([c92ee9b](https://github.com/LerianStudio/midaz/commit/c92ee9bc2649a3c46963027e067c4eed4dddade4)) +* add version onn .env file :sparkles: ([fdfdac3](https://github.com/LerianStudio/midaz/commit/fdfdac3bded8767307d7f1e3d68a3c76e5803aa8)) +* create new method listbyalias to find accounts based on transaction dsl info :sparkles: ([113c00c](https://github.com/LerianStudio/midaz/commit/113c00c2b64f2577f01460b1e4a017d3750f16ea)) +* create new route and server grpc and remove old account class :sparkles: ([c5d9101](https://github.com/LerianStudio/midaz/commit/c5d91011efbc8f0dca1c32091747a36abe3d6039)) +* generate new query to search account by ids :sparkles: ([aa5d147](https://github.com/LerianStudio/midaz/commit/aa5d147151fdbc814a41e7ba58496f8c3bce2989)) +* grpc server starting with http sever togheter :sparkles: ([6d12e14](https://github.com/LerianStudio/midaz/commit/6d12e140d21b28fe70d2f339a05cba4744cbce60)) +* update account by id and get account by alias by grpc :sparkles: ([bf98e11](https://github.com/LerianStudio/midaz/commit/bf98e11eba0e8a33eddd52e1cde4226deb5af872)) + + +### Bug Fixes + +* add -d on docker compose up :bug: ([0322e13](https://github.com/LerianStudio/midaz/commit/0322e13cf0cbbc1693cd21352ccb6f142b71d835)) +* adjust grpc account service :bug: ([2679e9b](https://github.com/LerianStudio/midaz/commit/2679e9bfe2d94fcc201e5672cec1f86feca5eb95)) +* change print error to return error :bug: ([2e28f92](https://github.com/LerianStudio/midaz/commit/2e28f9251b91fcfcd77a33492219f27f0bedb5b0)) +* go sec and go lint :bug: ([8a91b07](https://github.com/LerianStudio/midaz/commit/8a91b0746257afe7f4c4dc1ad6ce367b6f019cba)) +* remove fiber print startup :bug: ([d47dd20](https://github.com/LerianStudio/midaz/commit/d47dd20ba5c888860b9c07fceb4e4ff2b432a167)) +* reorganize some class and update wire. :bug: ([af0836b](https://github.com/LerianStudio/midaz/commit/af0836b86395b840b895eea7f1c256b04c5c7d17)) +* update version place in log :bug: ([83980a8](https://github.com/LerianStudio/midaz/commit/83980a8aee40884cb317914c40d89e13c12f6a68)) + +## [1.10.0-beta.1](https://github.com/LerianStudio/midaz/compare/v1.9.1-beta.1...v1.10.0-beta.1) (2024-09-17) + + +### Bug Fixes + +* add clean-up step for existing backup folder in PostgreSQL replica service in docker-compose ([28be466](https://github.com/LerianStudio/midaz/commit/28be466b7dda2f3dd100b73452c90d93ca574eda)) +* ensure pg_basebackup runs if directory or postgresql.conf file is missing ([9f9742e](https://github.com/LerianStudio/midaz/commit/9f9742e39fe223a7cda85252935ea0d1cbbf6b81)) + +## [1.9.1-beta.1](https://github.com/LerianStudio/midaz/compare/v1.9.0...v1.9.1-beta.1) (2024-09-17) + ## [1.9.0](https://github.com/LerianStudio/midaz/compare/v1.8.0...v1.9.0) (2024-09-16) diff --git a/common/app.go b/common/app.go index 97e56a88..c63afb6d 100644 --- a/common/app.go +++ b/common/app.go @@ -45,7 +45,7 @@ func (l *Launcher) Add(appName string, a App) *Launcher { return l } -// Run run every application registered before with Run method. +// Run every application registered before with Run method. func (l *Launcher) Run() { count := len(l.apps) l.wg.Add(count) diff --git a/common/os.go b/common/os.go index 287bff95..fb879688 100644 --- a/common/os.go +++ b/common/os.go @@ -69,14 +69,16 @@ var ( func InitLocalEnvConfig() *LocalEnvConfig { fmt.Println(console.Title("InitLocalEnvConfig")) + version := GetenvOrDefault("VERSION", "NO-VERSION") envName := GetenvOrDefault("ENV_NAME", "local") - fmt.Printf("ENVIRONMENT NAME \u001B[31m(%s)\u001B[0m\n", envName) + fmt.Printf("MIDAZ VERSION: \u001B[31m%s\u001B[0m\n", version) + fmt.Printf("ENVIRONMENT NAME: \u001B[31m(%s)\u001B[0m\n", envName) if envName == "local" { localEnvConfigOnce.Do(func() { if err := godotenv.Load(); err != nil { - fmt.Println("Skipping .env file. Current env ", envName) + fmt.Println("Skipping \u001B[31m.env\u001B[0m file, using env", envName) localEnvConfig = &LocalEnvConfig{ Initialized: false, diff --git a/components/ledger/.env.example b/components/ledger/.env.example index 8e5af8af..04453147 100644 --- a/components/ledger/.env.example +++ b/components/ledger/.env.example @@ -1,6 +1,10 @@ #ENV_NAME=production #default local +VERSION=1.8.0 SERVER_PORT=3000 SERVER_ADDRESS=:${SERVER_PORT} +PROTO_URL=localhost +PROTO_PORT=8765 +PROTO_ADDRESS=:${PROTO_PORT} MONGO_HOST=mongodb MONGO_NAME=ledger MONGO_USER=midaz diff --git a/components/ledger/Dockerfile b/components/ledger/Dockerfile index b548ae48..99a1c2a2 100644 --- a/components/ledger/Dockerfile +++ b/components/ledger/Dockerfile @@ -15,6 +15,6 @@ COPY --chown=nonroot:nonroot --from=builder /ledger-app/components/ledger/migrat USER nonroot -EXPOSE 3000 +EXPOSE 3000 50051 ENTRYPOINT ["/app"] \ No newline at end of file diff --git a/components/ledger/docker-compose.yml b/components/ledger/docker-compose.yml index c26af873..6e400d40 100644 --- a/components/ledger/docker-compose.yml +++ b/components/ledger/docker-compose.yml @@ -46,6 +46,7 @@ services: - replica-ledger ports: - ${SERVER_PORT}:${SERVER_PORT} + - ${PROTO_PORT}:${PROTO_PORT} volumes: - .:/usr/src/app depends_on: @@ -108,15 +109,17 @@ services: PGPASSWORD: ${REPLICATION_PASSWORD} command: | bash -c " - until pg_basebackup --pgdata=/var/lib/postgresql/data -R --slot=replication_slot --host=primary-ledger --port=${DB_PORT} - do - echo 'Waiting for primary-ledger to connect...' - sleep 1s - done - echo 'Backup done..., starting replica-ledger...' - chmod 0700 /var/lib/postgresql/data - # Ensure the port is set to 5433 for the replica - sed -i 's/^#port.*/port = ${DB_REPLICA_PORT}/' /var/lib/postgresql/data/postgresql.conf + if [ ! -d \"/var/lib/postgresql/data\" ] || [ ! -f \"/var/lib/postgresql/data/postgresql.conf\" ]; then + until pg_basebackup --pgdata=/var/lib/postgresql/data -R --slot=replication_slot --host=primary-ledger --port=${DB_PORT} + do + echo 'Waiting for primary-ledger to connect...' + sleep 1s + done + echo 'Backup done..., starting replica-ledger...' + chmod 0700 /var/lib/postgresql/data + # Ensure the port is set to 5433 for the replica + sed -i 's/^#port.*/port = ${DB_REPLICA_PORT}/' /var/lib/postgresql/data/postgresql.conf + fi exec postgres -c config_file=/var/lib/postgresql/data/postgresql.conf " healthcheck: diff --git a/components/ledger/internal/adapters/database/postgres/account.postgresql.go b/components/ledger/internal/adapters/database/postgres/account.postgresql.go index 60c47142..18c7d21a 100644 --- a/components/ledger/internal/adapters/database/postgres/account.postgresql.go +++ b/components/ledger/internal/adapters/database/postgres/account.postgresql.go @@ -302,6 +302,60 @@ func (r *AccountPostgreSQLRepository) ListByIDs(ctx context.Context, organizatio return accounts, nil } +// ListByAlias retrieves Accounts entities from the database using the provided alias. +func (r *AccountPostgreSQLRepository) ListByAlias(ctx context.Context, organizationID, ledgerID, portfolioID uuid.UUID, alias []string) ([]*a.Account, error) { + db, err := r.connection.GetDB() + if err != nil { + return nil, err + } + + var accounts []*a.Account + + rows, err := db.QueryContext(ctx, "SELECT * FROM account WHERE organization_id = $1 AND ledger_id = $2 AND portfolio_id = $3 AND alias = ANY($4) AND deleted_at IS NULL ORDER BY created_at DESC", + organizationID, ledgerID, portfolioID, pq.Array(alias)) + if err != nil { + return nil, err + } + defer rows.Close() + + for rows.Next() { + var acc a.AccountPostgreSQLModel + if err := rows.Scan( + &acc.ID, + &acc.Name, + &acc.ParentAccountID, + &acc.EntityID, + &acc.InstrumentCode, + &acc.OrganizationID, + &acc.LedgerID, + &acc.PortfolioID, + &acc.ProductID, + &acc.AvailableBalance, + &acc.OnHoldBalance, + &acc.BalanceScale, + &acc.Status, + &acc.StatusDescription, + &acc.AllowSending, + &acc.AllowReceiving, + &acc.Alias, + &acc.Type, + &acc.CreatedAt, + &acc.UpdatedAt, + &acc.DeletedAt, + ); err != nil { + return nil, err + } + + accounts = append(accounts, acc.ToEntity()) + } + + if err := rows.Err(); err != nil { + return nil, err + } + + return accounts, nil +} + // Update an Account entity into Postgresql and returns the Account updated. func (r *AccountPostgreSQLRepository) Update(ctx context.Context, organizationID, ledgerID, portfolioID, id uuid.UUID, account *a.Account) (*a.Account, error) { db, err := r.connection.GetDB() @@ -404,3 +458,170 @@ func (r *AccountPostgreSQLRepository) Delete(ctx context.Context, organizationID return nil } + +// ListAccountsByIDs list Accounts entity from the database using the provided IDs. +func (r *AccountPostgreSQLRepository) ListAccountsByIDs(ctx context.Context, ids []uuid.UUID) ([]*a.Account, error) { + db, err := r.connection.GetDB() + if err != nil { + return nil, err + } + + var accounts []*a.Account + + rows, err := db.QueryContext(ctx, "SELECT * FROM account WHERE id = ANY($1) AND deleted_at IS NULL ORDER BY created_at DESC", pq.Array(ids)) + if err != nil { + return nil, err + } + defer rows.Close() + + for rows.Next() { + var acc a.AccountPostgreSQLModel + if err := rows.Scan( + &acc.ID, + &acc.Name, + &acc.ParentAccountID, + &acc.EntityID, + &acc.InstrumentCode, + &acc.OrganizationID, + &acc.LedgerID, + &acc.PortfolioID, + &acc.ProductID, + &acc.AvailableBalance, + &acc.OnHoldBalance, + &acc.BalanceScale, + &acc.Status, + &acc.StatusDescription, + &acc.AllowSending, + &acc.AllowReceiving, + &acc.Alias, + &acc.Type, + &acc.CreatedAt, + &acc.UpdatedAt, + &acc.DeletedAt, + ); err != nil { + return nil, err + } + + accounts = append(accounts, acc.ToEntity()) + } + + if err := rows.Err(); err != nil { + return nil, err + } + + return accounts, nil +} + +// ListAccountsByAlias list Accounts entity from the database using the provided alias. +func (r *AccountPostgreSQLRepository) ListAccountsByAlias(ctx context.Context, aliases []string) ([]*a.Account, error) { + db, err := r.connection.GetDB() + if err != nil { + return nil, err + } + + var accounts []*a.Account + + rows, err := db.QueryContext(ctx, "SELECT * FROM account WHERE alias = ANY($1) AND deleted_at IS NULL ORDER BY created_at DESC", pq.Array(aliases)) + if err != nil { + return nil, err + } + defer rows.Close() + + for rows.Next() { + var acc a.AccountPostgreSQLModel + if err := rows.Scan( + &acc.ID, + &acc.Name, + &acc.ParentAccountID, + &acc.EntityID, + &acc.InstrumentCode, + &acc.OrganizationID, + &acc.LedgerID, + &acc.PortfolioID, + &acc.ProductID, + &acc.AvailableBalance, + &acc.OnHoldBalance, + &acc.BalanceScale, + &acc.Status, + &acc.StatusDescription, + &acc.AllowSending, + &acc.AllowReceiving, + &acc.Alias, + &acc.Type, + &acc.CreatedAt, + &acc.UpdatedAt, + &acc.DeletedAt, + ); err != nil { + return nil, err + } + + accounts = append(accounts, acc.ToEntity()) + } + + if err := rows.Err(); err != nil { + return nil, err + } + + return accounts, nil +} + +// UpdateAccountByID an update Account entity by ID only into Postgresql and returns the Account updated. +func (r *AccountPostgreSQLRepository) UpdateAccountByID(ctx context.Context, id uuid.UUID, account *a.Account) (*a.Account, error) { + db, err := r.connection.GetDB() + if err != nil { + return nil, err + } + + record := &a.AccountPostgreSQLModel{} + record.FromEntity(account) + + var updates []string + + var args []any + + if !account.Balance.IsEmpty() { + updates = append(updates, "available_balance = $"+strconv.Itoa(len(args)+1)) + args = append(args, record.AvailableBalance) + + updates = append(updates, "on_hold_balance = $"+strconv.Itoa(len(args)+1)) + args = append(args, record.OnHoldBalance) + + updates = append(updates, "balance_scale = $"+strconv.Itoa(len(args)+1)) + args = append(args, record.BalanceScale) + } + + record.UpdatedAt = time.Now() + + updates = append(updates, "updated_at = $"+strconv.Itoa(len(args)+1)) + args = append(args, record.UpdatedAt, id) + + query := `UPDATE account SET ` + strings.Join(updates, ", ") + + ` WHERE id = $` + strconv.Itoa(len(args)) + + ` AND deleted_at IS NULL` + + result, err := db.ExecContext(ctx, query, args...) + if err != nil { + var pgErr *pgconn.PgError + if errors.As(err, &pgErr) { + return nil, app.ValidatePGError(pgErr, reflect.TypeOf(a.Account{}).Name()) + } + + return nil, err + } + + rowsAffected, err := result.RowsAffected() + if err != nil { + return nil, err + } + + if rowsAffected == 0 { + return nil, common.EntityNotFoundError{ + EntityType: reflect.TypeOf(a.Account{}).Name(), + Title: "Entity not found.", + Code: "0007", + Message: "No entity was found matching the provided ID. Ensure the correct ID is being used for the entity you are attempting to manage.", + } + } + + return record.ToEntity(), nil +} diff --git a/components/ledger/internal/app/command/update-account-id.go b/components/ledger/internal/app/command/update-account-id.go new file mode 100644 index 00000000..44bbe04a --- /dev/null +++ b/components/ledger/internal/app/command/update-account-id.go @@ -0,0 +1,42 @@ +package command + +import ( + "context" + "errors" + "fmt" + "reflect" + + "github.com/LerianStudio/midaz/common" + "github.com/LerianStudio/midaz/common/mlog" + "github.com/LerianStudio/midaz/components/ledger/internal/app" + a "github.com/LerianStudio/midaz/components/ledger/internal/domain/portfolio/account" + "github.com/google/uuid" +) + +// UpdateAccountByID update an account from the repository by given id. +func (uc *UseCase) UpdateAccountByID(ctx context.Context, id string, balance *a.Balance) (*a.Account, error) { + logger := mlog.NewLoggerFromContext(ctx) + logger.Infof("Trying to update account by id: %v", id) + + account := &a.Account{ + Balance: *balance, + } + + accountUpdated, err := uc.AccountRepo.UpdateAccountByID(ctx, uuid.MustParse(id), account) + if err != nil { + logger.Errorf("Error updating account on repo by id: %v", err) + + if errors.Is(err, app.ErrDatabaseItemNotFound) { + return nil, common.EntityNotFoundError{ + EntityType: reflect.TypeOf(a.Account{}).Name(), + Message: fmt.Sprintf("Account with id %s was not found", id), + Code: "ACCOUNT_NOT_FOUND", + Err: err, + } + } + + return nil, err + } + + return accountUpdated, nil +} diff --git a/components/ledger/internal/app/command/update-account.go b/components/ledger/internal/app/command/update-account.go index 00921ed6..4223122b 100644 --- a/components/ledger/internal/app/command/update-account.go +++ b/components/ledger/internal/app/command/update-account.go @@ -13,8 +13,8 @@ import ( "github.com/google/uuid" ) -// UpdateAccountByID update an account from the repository by given id. -func (uc *UseCase) UpdateAccountByID(ctx context.Context, organizationID, ledgerID, portfolioID, id string, uai *a.UpdateAccountInput) (*a.Account, error) { +// UpdateAccount update an account from the repository by given id. +func (uc *UseCase) UpdateAccount(ctx context.Context, organizationID, ledgerID, portfolioID, id string, uai *a.UpdateAccountInput) (*a.Account, error) { logger := mlog.NewLoggerFromContext(ctx) logger.Infof("Trying to update account: %v", uai) diff --git a/components/ledger/internal/app/query/get-alias-accounts.go b/components/ledger/internal/app/query/get-alias-accounts.go new file mode 100644 index 00000000..da2e9151 --- /dev/null +++ b/components/ledger/internal/app/query/get-alias-accounts.go @@ -0,0 +1,36 @@ +package query + +import ( + "context" + "errors" + "reflect" + + "github.com/LerianStudio/midaz/common" + "github.com/LerianStudio/midaz/common/mlog" + "github.com/LerianStudio/midaz/components/ledger/internal/app" + a "github.com/LerianStudio/midaz/components/ledger/internal/domain/portfolio/account" +) + +// ListAccountsByAlias get Accounts from the repository by given alias. +func (uc *UseCase) ListAccountsByAlias(ctx context.Context, aliases []string) ([]*a.Account, error) { + logger := mlog.NewLoggerFromContext(ctx) + logger.Infof("Retrieving account for alias: %s", aliases) + + accounts, err := uc.AccountRepo.ListAccountsByAlias(ctx, aliases) + if err != nil { + logger.Errorf("Error getting accounts on repo: %v", err) + + if errors.Is(err, app.ErrDatabaseItemNotFound) { + return nil, common.EntityNotFoundError{ + EntityType: reflect.TypeOf(a.Account{}).Name(), + Message: "Account was not found", + Code: "ACCOUNT_NOT_FOUND", + Err: err, + } + } + + return nil, err + } + + return accounts, nil +} diff --git a/components/ledger/internal/app/query/get-ids-accounts.go b/components/ledger/internal/app/query/get-ids-accounts.go new file mode 100644 index 00000000..a159586d --- /dev/null +++ b/components/ledger/internal/app/query/get-ids-accounts.go @@ -0,0 +1,37 @@ +package query + +import ( + "context" + "errors" + "reflect" + + "github.com/LerianStudio/midaz/common" + "github.com/LerianStudio/midaz/common/mlog" + "github.com/LerianStudio/midaz/components/ledger/internal/app" + a "github.com/LerianStudio/midaz/components/ledger/internal/domain/portfolio/account" + "github.com/google/uuid" +) + +// ListAccountsByIDs get Accounts from the repository by given ids. +func (uc *UseCase) ListAccountsByIDs(ctx context.Context, ids []uuid.UUID) ([]*a.Account, error) { + logger := mlog.NewLoggerFromContext(ctx) + logger.Infof("Retrieving account for id: %s", ids) + + accounts, err := uc.AccountRepo.ListAccountsByIDs(ctx, ids) + if err != nil { + logger.Errorf("Error getting accounts on repo: %v", err) + + if errors.Is(err, app.ErrDatabaseItemNotFound) { + return nil, common.EntityNotFoundError{ + EntityType: reflect.TypeOf(a.Account{}).Name(), + Message: "Account was not found", + Code: "ACCOUNT_NOT_FOUND", + Err: err, + } + } + + return nil, err + } + + return accounts, nil +} diff --git a/components/ledger/internal/domain/portfolio/account/account_repository.go b/components/ledger/internal/domain/portfolio/account/account_repository.go index e85e2768..89719403 100644 --- a/components/ledger/internal/domain/portfolio/account/account_repository.go +++ b/components/ledger/internal/domain/portfolio/account/account_repository.go @@ -15,6 +15,10 @@ type Repository interface { Find(ctx context.Context, organizationID, ledgerID, portfolioID, id uuid.UUID) (*Account, error) FindByAlias(ctx context.Context, organizationID, ledgerID, portfolioID uuid.UUID, alias string) (bool, error) ListByIDs(ctx context.Context, organizationID, ledgerID, portfolioID uuid.UUID, ids []uuid.UUID) ([]*Account, error) + ListByAlias(ctx context.Context, organizationID, ledgerID, portfolioID uuid.UUID, alias []string) ([]*Account, error) Update(ctx context.Context, organizationID, ledgerID, portfolioID, id uuid.UUID, account *Account) (*Account, error) Delete(ctx context.Context, organizationID, ledgerID, portfolioID, id uuid.UUID) error + ListAccountsByIDs(ctx context.Context, ids []uuid.UUID) ([]*Account, error) + ListAccountsByAlias(ctx context.Context, aliases []string) ([]*Account, error) + UpdateAccountByID(ctx context.Context, id uuid.UUID, account *Account) (*Account, error) } diff --git a/components/ledger/internal/gen/inject.go b/components/ledger/internal/gen/inject.go index 232a2613..f4c5dc21 100644 --- a/components/ledger/internal/gen/inject.go +++ b/components/ledger/internal/gen/inject.go @@ -5,26 +5,25 @@ package gen import ( "fmt" - "github.com/LerianStudio/midaz/components/ledger/internal/adapters/database/mongodb" - "github.com/LerianStudio/midaz/components/ledger/internal/adapters/database/postgres" - "github.com/LerianStudio/midaz/components/ledger/internal/domain/onboarding/ledger" - "github.com/LerianStudio/midaz/components/ledger/internal/domain/onboarding/organization" - "github.com/LerianStudio/midaz/components/ledger/internal/domain/portfolio/account" - "github.com/LerianStudio/midaz/components/ledger/internal/domain/portfolio/instrument" - "github.com/LerianStudio/midaz/components/ledger/internal/domain/portfolio/portfolio" - "github.com/LerianStudio/midaz/components/ledger/internal/domain/portfolio/product" - "github.com/LerianStudio/midaz/components/ledger/internal/ports" "sync" - "github.com/LerianStudio/midaz/common/mmongo" - "github.com/LerianStudio/midaz/common" + "github.com/LerianStudio/midaz/common/mmongo" "github.com/LerianStudio/midaz/common/mpostgres" "github.com/LerianStudio/midaz/common/mzap" + "github.com/LerianStudio/midaz/components/ledger/internal/adapters/database/mongodb" + "github.com/LerianStudio/midaz/components/ledger/internal/adapters/database/postgres" "github.com/LerianStudio/midaz/components/ledger/internal/app/command" "github.com/LerianStudio/midaz/components/ledger/internal/app/query" "github.com/LerianStudio/midaz/components/ledger/internal/domain/metadata" - httpHandler "github.com/LerianStudio/midaz/components/ledger/internal/ports/http" + "github.com/LerianStudio/midaz/components/ledger/internal/domain/onboarding/ledger" + "github.com/LerianStudio/midaz/components/ledger/internal/domain/onboarding/organization" + "github.com/LerianStudio/midaz/components/ledger/internal/domain/portfolio/account" + "github.com/LerianStudio/midaz/components/ledger/internal/domain/portfolio/instrument" + "github.com/LerianStudio/midaz/components/ledger/internal/domain/portfolio/portfolio" + "github.com/LerianStudio/midaz/components/ledger/internal/domain/portfolio/product" + portsGRPC "github.com/LerianStudio/midaz/components/ledger/internal/ports/grpc" + portsHTTP "github.com/LerianStudio/midaz/components/ledger/internal/ports/http" "github.com/LerianStudio/midaz/components/ledger/internal/service" "github.com/google/wire" ) @@ -65,8 +64,10 @@ var ( mzap.InitializeLogger, setupPostgreSQLConnection, setupMongoDBConnection, + portsGRPC.NewRouterGRPC, + service.NewServerGRPC, + portsHTTP.NewRouter, service.NewConfig, - httpHandler.NewRouter, service.NewServer, postgres.NewOrganizationPostgreSQLRepository, postgres.NewLedgerPostgreSQLRepository, @@ -75,12 +76,12 @@ var ( postgres.NewProductPostgreSQLRepository, postgres.NewAccountPostgreSQLRepository, mongodb.NewMetadataMongoDBRepository, - wire.Struct(new(ports.OrganizationHandler), "*"), - wire.Struct(new(ports.LedgerHandler), "*"), - wire.Struct(new(ports.InstrumentHandler), "*"), - wire.Struct(new(ports.PortfolioHandler), "*"), - wire.Struct(new(ports.ProductHandler), "*"), - wire.Struct(new(ports.AccountHandler), "*"), + wire.Struct(new(portsHTTP.OrganizationHandler), "*"), + wire.Struct(new(portsHTTP.LedgerHandler), "*"), + wire.Struct(new(portsHTTP.InstrumentHandler), "*"), + wire.Struct(new(portsHTTP.PortfolioHandler), "*"), + wire.Struct(new(portsHTTP.ProductHandler), "*"), + wire.Struct(new(portsHTTP.AccountHandler), "*"), wire.Struct(new(command.UseCase), "*"), wire.Struct(new(query.UseCase), "*"), wire.Bind(new(organization.Repository), new(*postgres.OrganizationPostgreSQLRepository)), @@ -93,7 +94,7 @@ var ( ) svcSet = wire.NewSet( - wire.Struct(new(service.Service), "Server", "Logger"), + wire.Struct(new(service.Service), "Server", "ServerGRPC", "Logger"), ) ) diff --git a/components/ledger/internal/gen/mock/account/account_mock.go b/components/ledger/internal/gen/mock/account/account_mock.go index bf3547c9..92d89908 100644 --- a/components/ledger/internal/gen/mock/account/account_mock.go +++ b/components/ledger/internal/gen/mock/account/account_mock.go @@ -115,6 +115,51 @@ func (mr *MockRepositoryMockRecorder) FindByAlias(arg0, arg1, arg2, arg3, arg4 a return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FindByAlias", reflect.TypeOf((*MockRepository)(nil).FindByAlias), arg0, arg1, arg2, arg3, arg4) } +// ListAccountsByAlias mocks base method. +func (m *MockRepository) ListAccountsByAlias(arg0 context.Context, arg1 []string) ([]*account.Account, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ListAccountsByAlias", arg0, arg1) + ret0, _ := ret[0].([]*account.Account) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ListAccountsByAlias indicates an expected call of ListAccountsByAlias. +func (mr *MockRepositoryMockRecorder) ListAccountsByAlias(arg0, arg1 any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ListAccountsByAlias", reflect.TypeOf((*MockRepository)(nil).ListAccountsByAlias), arg0, arg1) +} + +// ListAccountsByIDs mocks base method. +func (m *MockRepository) ListAccountsByIDs(arg0 context.Context, arg1 []uuid.UUID) ([]*account.Account, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ListAccountsByIDs", arg0, arg1) + ret0, _ := ret[0].([]*account.Account) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ListAccountsByIDs indicates an expected call of ListAccountsByIDs. +func (mr *MockRepositoryMockRecorder) ListAccountsByIDs(arg0, arg1 any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ListAccountsByIDs", reflect.TypeOf((*MockRepository)(nil).ListAccountsByIDs), arg0, arg1) +} + +// ListByAlias mocks base method. +func (m *MockRepository) ListByAlias(arg0 context.Context, arg1, arg2, arg3 uuid.UUID, arg4 []string) ([]*account.Account, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ListByAlias", arg0, arg1, arg2, arg3, arg4) + ret0, _ := ret[0].([]*account.Account) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// ListByAlias indicates an expected call of ListByAlias. +func (mr *MockRepositoryMockRecorder) ListByAlias(arg0, arg1, arg2, arg3, arg4 any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ListByAlias", reflect.TypeOf((*MockRepository)(nil).ListByAlias), arg0, arg1, arg2, arg3, arg4) +} + // ListByIDs mocks base method. func (m *MockRepository) ListByIDs(arg0 context.Context, arg1, arg2, arg3 uuid.UUID, arg4 []uuid.UUID) ([]*account.Account, error) { m.ctrl.T.Helper() @@ -144,3 +189,18 @@ func (mr *MockRepositoryMockRecorder) Update(arg0, arg1, arg2, arg3, arg4, arg5 mr.mock.ctrl.T.Helper() return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Update", reflect.TypeOf((*MockRepository)(nil).Update), arg0, arg1, arg2, arg3, arg4, arg5) } + +// UpdateAccountByID mocks base method. +func (m *MockRepository) UpdateAccountByID(arg0 context.Context, arg1 uuid.UUID, arg2 *account.Account) (*account.Account, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "UpdateAccountByID", arg0, arg1, arg2) + ret0, _ := ret[0].(*account.Account) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// UpdateAccountByID indicates an expected call of UpdateAccountByID. +func (mr *MockRepositoryMockRecorder) UpdateAccountByID(arg0, arg1, arg2 any) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateAccountByID", reflect.TypeOf((*MockRepository)(nil).UpdateAccountByID), arg0, arg1, arg2) +} diff --git a/components/ledger/internal/gen/wire_gen.go b/components/ledger/internal/gen/wire_gen.go index 1bad0ba4..d3ad010d 100644 --- a/components/ledger/internal/gen/wire_gen.go +++ b/components/ledger/internal/gen/wire_gen.go @@ -23,7 +23,7 @@ import ( "github.com/LerianStudio/midaz/components/ledger/internal/domain/portfolio/instrument" "github.com/LerianStudio/midaz/components/ledger/internal/domain/portfolio/portfolio" "github.com/LerianStudio/midaz/components/ledger/internal/domain/portfolio/product" - "github.com/LerianStudio/midaz/components/ledger/internal/ports" + "github.com/LerianStudio/midaz/components/ledger/internal/ports/grpc" "github.com/LerianStudio/midaz/components/ledger/internal/ports/http" "github.com/LerianStudio/midaz/components/ledger/internal/service" "github.com/google/wire" @@ -62,36 +62,39 @@ func InitializeService() *service.Service { InstrumentRepo: instrumentPostgreSQLRepository, MetadataRepo: metadataMongoDBRepository, } - accountHandler := &ports.AccountHandler{ + accountHandler := &http.AccountHandler{ Command: useCase, Query: queryUseCase, } - portfolioHandler := &ports.PortfolioHandler{ + portfolioHandler := &http.PortfolioHandler{ Command: useCase, Query: queryUseCase, } - ledgerHandler := &ports.LedgerHandler{ + ledgerHandler := &http.LedgerHandler{ Command: useCase, Query: queryUseCase, } - instrumentHandler := &ports.InstrumentHandler{ + instrumentHandler := &http.InstrumentHandler{ Command: useCase, Query: queryUseCase, } - organizationHandler := &ports.OrganizationHandler{ + organizationHandler := &http.OrganizationHandler{ Command: useCase, Query: queryUseCase, } - productHandler := &ports.ProductHandler{ + productHandler := &http.ProductHandler{ Command: useCase, Query: queryUseCase, } app := http.NewRouter(accountHandler, portfolioHandler, ledgerHandler, instrumentHandler, organizationHandler, productHandler) logger := mzap.InitializeLogger() server := service.NewServer(config, app, logger) + grpcServer := grpc.NewRouterGRPC(useCase, queryUseCase) + serverGRPC := service.NewServerGRPC(config, grpcServer, logger) serviceService := &service.Service{ - Server: server, - Logger: logger, + Server: server, + ServerGRPC: serverGRPC, + Logger: logger, } return serviceService } @@ -130,8 +133,8 @@ func setupMongoDBConnection(cfg *service.Config) *mmongo.MongoConnection { var ( serviceSet = wire.NewSet(common.InitLocalEnvConfig, mzap.InitializeLogger, setupPostgreSQLConnection, - setupMongoDBConnection, service.NewConfig, http.NewRouter, service.NewServer, postgres.NewOrganizationPostgreSQLRepository, postgres.NewLedgerPostgreSQLRepository, postgres.NewInstrumentPostgreSQLRepository, postgres.NewPortfolioPostgreSQLRepository, postgres.NewProductPostgreSQLRepository, postgres.NewAccountPostgreSQLRepository, mongodb.NewMetadataMongoDBRepository, wire.Struct(new(ports.OrganizationHandler), "*"), wire.Struct(new(ports.LedgerHandler), "*"), wire.Struct(new(ports.InstrumentHandler), "*"), wire.Struct(new(ports.PortfolioHandler), "*"), wire.Struct(new(ports.ProductHandler), "*"), wire.Struct(new(ports.AccountHandler), "*"), wire.Struct(new(command.UseCase), "*"), wire.Struct(new(query.UseCase), "*"), wire.Bind(new(organization.Repository), new(*postgres.OrganizationPostgreSQLRepository)), wire.Bind(new(ledger.Repository), new(*postgres.LedgerPostgreSQLRepository)), wire.Bind(new(instrument.Repository), new(*postgres.InstrumentPostgreSQLRepository)), wire.Bind(new(portfolio.Repository), new(*postgres.PortfolioPostgreSQLRepository)), wire.Bind(new(product.Repository), new(*postgres.ProductPostgreSQLRepository)), wire.Bind(new(account.Repository), new(*postgres.AccountPostgreSQLRepository)), wire.Bind(new(metadata.Repository), new(*mongodb.MetadataMongoDBRepository)), + setupMongoDBConnection, grpc.NewRouterGRPC, service.NewServerGRPC, http.NewRouter, service.NewConfig, service.NewServer, postgres.NewOrganizationPostgreSQLRepository, postgres.NewLedgerPostgreSQLRepository, postgres.NewInstrumentPostgreSQLRepository, postgres.NewPortfolioPostgreSQLRepository, postgres.NewProductPostgreSQLRepository, postgres.NewAccountPostgreSQLRepository, mongodb.NewMetadataMongoDBRepository, wire.Struct(new(http.OrganizationHandler), "*"), wire.Struct(new(http.LedgerHandler), "*"), wire.Struct(new(http.InstrumentHandler), "*"), wire.Struct(new(http.PortfolioHandler), "*"), wire.Struct(new(http.ProductHandler), "*"), wire.Struct(new(http.AccountHandler), "*"), wire.Struct(new(command.UseCase), "*"), wire.Struct(new(query.UseCase), "*"), wire.Bind(new(organization.Repository), new(*postgres.OrganizationPostgreSQLRepository)), wire.Bind(new(ledger.Repository), new(*postgres.LedgerPostgreSQLRepository)), wire.Bind(new(instrument.Repository), new(*postgres.InstrumentPostgreSQLRepository)), wire.Bind(new(portfolio.Repository), new(*postgres.PortfolioPostgreSQLRepository)), wire.Bind(new(product.Repository), new(*postgres.ProductPostgreSQLRepository)), wire.Bind(new(account.Repository), new(*postgres.AccountPostgreSQLRepository)), wire.Bind(new(metadata.Repository), new(*mongodb.MetadataMongoDBRepository)), ) - svcSet = wire.NewSet(wire.Struct(new(service.Service), "Server", "Logger")) + svcSet = wire.NewSet(wire.Struct(new(service.Service), "Server", "ServerGRPC", "Logger")) ) diff --git a/components/ledger/internal/ports/grpc/account.go b/components/ledger/internal/ports/grpc/account.go new file mode 100644 index 00000000..d94517b7 --- /dev/null +++ b/components/ledger/internal/ports/grpc/account.go @@ -0,0 +1,140 @@ +package grpc + +import ( + "context" + + "github.com/LerianStudio/midaz/common" + "github.com/LerianStudio/midaz/common/mlog" + "github.com/LerianStudio/midaz/components/ledger/internal/app/command" + "github.com/LerianStudio/midaz/components/ledger/internal/app/query" + a "github.com/LerianStudio/midaz/components/ledger/internal/domain/portfolio/account" + proto "github.com/LerianStudio/midaz/components/ledger/proto/account" + "github.com/google/uuid" +) + +// AccountProto struct contains an account use case for managing account related operations. +type AccountProto struct { + Command *command.UseCase + Query *query.UseCase + proto.UnimplementedAccountProtoServer +} + +// GetByIds is a method that retrieves Account information by a given ids. +func (ap *AccountProto) GetByIds(ctx context.Context, ids *proto.ManyAccountsID) (*proto.ManyAccountsResponse, error) { + logger := mlog.NewLoggerFromContext(ctx) + + uuids := make([]uuid.UUID, len(ids.Ids)) + for i, id := range ids.Ids { + uuids[i] = uuid.MustParse(id.Id) + } + + acc, err := ap.Query.ListAccountsByIDs(ctx, uuids) + if err != nil { + logger.Errorf("Failed to retrieve Accounts by ids for grpc, Error: %s", err.Error()) + + return nil, common.ValidationError{ + Code: "0001", + Message: "Failed to retrieve Accounts by ids for grpc", + } + } + + accounts := make([]*proto.Account, len(acc)) + + for _, ac := range acc { + account := proto.Account{ + Id: ac.ID, + Alias: *ac.Alias, + AvailableBalance: *ac.Balance.Available, + OnHoldBalance: *ac.Balance.OnHold, + BalanceScale: *ac.Balance.Scale, + AllowSending: ac.Status.AllowSending, + AllowReceiving: ac.Status.AllowReceiving, + } + accounts = append(accounts, &account) + } + + response := proto.ManyAccountsResponse{ + Accounts: accounts, + } + + return &response, nil +} + +func (ap *AccountProto) GetByAlias(ctx context.Context, aliases *proto.ManyAccountsAlias) (*proto.ManyAccountsResponse, error) { + logger := mlog.NewLoggerFromContext(ctx) + + als := make([]string, len(aliases.Aliases)) + for i, aA := range aliases.Aliases { + als[i] = aA.Alias + } + + acc, err := ap.Query.ListAccountsByAlias(ctx, als) + if err != nil { + logger.Errorf("Failed to retrieve Accounts by aliases for grpc, Error: %s", err.Error()) + + return nil, common.ValidationError{ + Code: "0001", + Message: "Failed to retrieve Accounts by aliases for grpc", + } + } + + accounts := make([]*proto.Account, len(acc)) + + for _, ac := range acc { + account := proto.Account{ + Id: ac.ID, + Alias: *ac.Alias, + AvailableBalance: *ac.Balance.Available, + OnHoldBalance: *ac.Balance.OnHold, + BalanceScale: *ac.Balance.Scale, + AllowSending: ac.Status.AllowSending, + AllowReceiving: ac.Status.AllowReceiving, + } + accounts = append(accounts, &account) + } + + response := proto.ManyAccountsResponse{ + Accounts: accounts, + } + + return &response, nil +} + +func (ap *AccountProto) Update(ctx context.Context, update *proto.UpdateRequest) (*proto.Account, error) { + logger := mlog.NewLoggerFromContext(ctx) + + if common.IsNilOrEmpty(&update.Id) { + logger.Errorf("Failed to update Accounts because id is empty") + + return nil, common.ValidationError{ + Code: "0001", + Message: "Failed to update Accounts because id is empty", + } + } + + balance := a.Balance{ + Available: &update.AvailableBalance, + OnHold: &update.OnHoldBalance, + Scale: &update.BalanceScale, + } + + acu, err := ap.Command.UpdateAccountByID(ctx, update.Id, &balance) + if err != nil { + logger.Errorf("Failed to update balance in Account by id for grpc, Error: %s", err.Error()) + + return nil, common.ValidationError{ + Code: "0002", + Message: "Failed to update balance in Account by id for grpc", + } + } + + account := proto.Account{ + Id: acu.ID, + Alias: update.Alias, + AvailableBalance: *acu.Balance.Available, + OnHoldBalance: *acu.Balance.OnHold, + BalanceScale: *acu.Balance.Scale, + } + + return &account, nil +} diff --git a/components/ledger/internal/ports/grpc/routes.go b/components/ledger/internal/ports/grpc/routes.go new file mode 100644 index 00000000..027f57a7 --- /dev/null +++ b/components/ledger/internal/ports/grpc/routes.go @@ -0,0 +1,28 @@ +package grpc + +import ( + "github.com/LerianStudio/midaz/components/ledger/internal/app/command" + "github.com/LerianStudio/midaz/components/ledger/internal/app/query" + "github.com/LerianStudio/midaz/components/ledger/internal/service" + proto "github.com/LerianStudio/midaz/components/ledger/proto/account" + "google.golang.org/grpc" + "google.golang.org/grpc/reflection" +) + +// NewRouterGRPC registers routes to the grpc. +func NewRouterGRPC(cuc *command.UseCase, quc *query.UseCase) *grpc.Server { + server := grpc.NewServer() + + _ = service.NewConfig() + + reflection.Register(server) + + ap := &AccountProto{ + Command: cuc, + Query: quc, + } + + proto.RegisterAccountProtoServer(server, ap) + + return server +} diff --git a/components/ledger/internal/ports/account.go b/components/ledger/internal/ports/http/account.go similarity index 97% rename from components/ledger/internal/ports/account.go rename to components/ledger/internal/ports/http/account.go index 3d7b6010..0e4d1311 100644 --- a/components/ledger/internal/ports/account.go +++ b/components/ledger/internal/ports/http/account.go @@ -1,4 +1,4 @@ -package ports +package http import ( "github.com/LerianStudio/midaz/common/mlog" @@ -131,7 +131,7 @@ func (handler *AccountHandler) UpdateAccount(i any, c *fiber.Ctx) error { payload := i.(*a.UpdateAccountInput) logger.Infof("Request to update an Account with details: %#v", payload) - account, err := handler.Command.UpdateAccountByID(ctx, organizationID, ledgerID, portfolioID, id, payload) + account, err := handler.Command.UpdateAccount(ctx, organizationID, ledgerID, portfolioID, id, payload) if err != nil { logger.Errorf("Failed to update Account with ID: %s, Error: %s", id, err.Error()) return commonHTTP.WithError(c, err) diff --git a/components/ledger/internal/ports/instrument.go b/components/ledger/internal/ports/http/instrument.go similarity index 99% rename from components/ledger/internal/ports/instrument.go rename to components/ledger/internal/ports/http/instrument.go index 6cfd02ad..92b84aee 100644 --- a/components/ledger/internal/ports/instrument.go +++ b/components/ledger/internal/ports/http/instrument.go @@ -1,4 +1,4 @@ -package ports +package http import ( "github.com/LerianStudio/midaz/common/mlog" diff --git a/components/ledger/internal/ports/ledger.go b/components/ledger/internal/ports/http/ledger.go similarity index 99% rename from components/ledger/internal/ports/ledger.go rename to components/ledger/internal/ports/http/ledger.go index d4b2fb83..53eeab65 100644 --- a/components/ledger/internal/ports/ledger.go +++ b/components/ledger/internal/ports/http/ledger.go @@ -1,4 +1,4 @@ -package ports +package http import ( "os" diff --git a/components/ledger/internal/ports/organization.go b/components/ledger/internal/ports/http/organization.go similarity index 99% rename from components/ledger/internal/ports/organization.go rename to components/ledger/internal/ports/http/organization.go index e255c609..b42527c5 100644 --- a/components/ledger/internal/ports/organization.go +++ b/components/ledger/internal/ports/http/organization.go @@ -1,4 +1,4 @@ -package ports +package http import ( "os" diff --git a/components/ledger/internal/ports/portfolio.go b/components/ledger/internal/ports/http/portfolio.go similarity index 99% rename from components/ledger/internal/ports/portfolio.go rename to components/ledger/internal/ports/http/portfolio.go index a41be3c2..99ff0a4e 100644 --- a/components/ledger/internal/ports/portfolio.go +++ b/components/ledger/internal/ports/http/portfolio.go @@ -1,4 +1,4 @@ -package ports +package http import ( "github.com/LerianStudio/midaz/common/mlog" diff --git a/components/ledger/internal/ports/product.go b/components/ledger/internal/ports/http/product.go similarity index 99% rename from components/ledger/internal/ports/product.go rename to components/ledger/internal/ports/http/product.go index 02e5a0a3..582b2d9a 100644 --- a/components/ledger/internal/ports/product.go +++ b/components/ledger/internal/ports/http/product.go @@ -1,4 +1,4 @@ -package ports +package http import ( "github.com/LerianStudio/midaz/common/mlog" diff --git a/components/ledger/internal/ports/http/routes.go b/components/ledger/internal/ports/http/routes.go index 074adbc1..6c2fd7cd 100644 --- a/components/ledger/internal/ports/http/routes.go +++ b/components/ledger/internal/ports/http/routes.go @@ -8,15 +8,16 @@ import ( i "github.com/LerianStudio/midaz/components/ledger/internal/domain/portfolio/instrument" p "github.com/LerianStudio/midaz/components/ledger/internal/domain/portfolio/portfolio" r "github.com/LerianStudio/midaz/components/ledger/internal/domain/portfolio/product" - "github.com/LerianStudio/midaz/components/ledger/internal/ports" "github.com/LerianStudio/midaz/components/ledger/internal/service" "github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2/middleware/cors" ) // NewRouter registers routes to the Server. -func NewRouter(ah *ports.AccountHandler, ph *ports.PortfolioHandler, lh *ports.LedgerHandler, ih *ports.InstrumentHandler, oh *ports.OrganizationHandler, rh *ports.ProductHandler) *fiber.App { - f := fiber.New() +func NewRouter(ah *AccountHandler, ph *PortfolioHandler, lh *LedgerHandler, ih *InstrumentHandler, oh *OrganizationHandler, rh *ProductHandler) *fiber.App { + f := fiber.New(fiber.Config{ + DisableStartupMessage: true, + }) _ = service.NewConfig() diff --git a/components/ledger/internal/service/config.go b/components/ledger/internal/service/config.go index 6b054895..afd88e20 100644 --- a/components/ledger/internal/service/config.go +++ b/components/ledger/internal/service/config.go @@ -1,13 +1,14 @@ package service import ( - common "github.com/LerianStudio/midaz/common" + "github.com/LerianStudio/midaz/common" ) // Config is the top level configuration struct for the entire application. type Config struct { EnvName string `env:"ENV_NAME"` ServerAddress string `env:"SERVER_ADDRESS"` + ProtoAddress string `env:"PROTO_ADDRESS"` PrimaryDBHost string `env:"DB_HOST"` PrimaryDBUser string `env:"DB_USER"` PrimaryDBPassword string `env:"DB_PASSWORD"` @@ -25,7 +26,7 @@ type Config struct { MongoDBPort string `env:"MONGO_PORT"` } -// NewConfig creates a instance of Config. +// NewConfig creates an instance of Config. func NewConfig() *Config { cfg := &Config{} diff --git a/components/ledger/internal/service/server.go b/components/ledger/internal/service/server.go index f4570159..240fa4ff 100644 --- a/components/ledger/internal/service/server.go +++ b/components/ledger/internal/service/server.go @@ -1,7 +1,7 @@ package service import ( - common "github.com/LerianStudio/midaz/common" + "github.com/LerianStudio/midaz/common" "github.com/LerianStudio/midaz/common/mlog" "github.com/gofiber/fiber/v2" "github.com/pkg/errors" diff --git a/components/ledger/internal/service/servergRPC.go b/components/ledger/internal/service/servergRPC.go new file mode 100644 index 00000000..bfa7c767 --- /dev/null +++ b/components/ledger/internal/service/servergRPC.go @@ -0,0 +1,46 @@ +package service + +import ( + "net" + + "github.com/LerianStudio/midaz/common" + "github.com/LerianStudio/midaz/common/mlog" + "github.com/pkg/errors" + "google.golang.org/grpc" +) + +// ServerGRPC represents the gRPC server for Ledger service. +type ServerGRPC struct { + server *grpc.Server + protoAddress string + mlog.Logger +} + +// ProtoAddress returns is a convenience method to return the proto server address. +func (sgrpc *ServerGRPC) ProtoAddress() string { + return sgrpc.protoAddress +} + +// NewServerGRPC creates an instance of gRPC Server. +func NewServerGRPC(cfg *Config, server *grpc.Server, logger mlog.Logger) *ServerGRPC { + return &ServerGRPC{ + server: server, + protoAddress: cfg.ProtoAddress, + Logger: logger, + } +} + +// Run gRPC server. +func (sgrpc *ServerGRPC) Run(l *common.Launcher) error { + listen, err := net.Listen("tcp4", sgrpc.protoAddress) + if err != nil { + return errors.Wrap(err, "failed to listen tcp4 server") + } + + err = sgrpc.server.Serve(listen) + if err != nil { + return errors.Wrap(err, "failed to run the gRPC server") + } + + return nil +} diff --git a/components/ledger/internal/service/service.go b/components/ledger/internal/service/service.go index fc34c286..82d37adf 100644 --- a/components/ledger/internal/service/service.go +++ b/components/ledger/internal/service/service.go @@ -1,13 +1,14 @@ package service import ( - common "github.com/LerianStudio/midaz/common" + "github.com/LerianStudio/midaz/common" "github.com/LerianStudio/midaz/common/mlog" ) // Service is the application glue where we put all top level components to be used. type Service struct { *Server + *ServerGRPC mlog.Logger } @@ -16,6 +17,7 @@ type Service struct { func (app *Service) Run() { common.NewLauncher( common.WithLogger(app.Logger), - common.RunApp("service", app.Server), + common.RunApp("HTTP server", app.Server), + common.RunApp("gRPC server", app.ServerGRPC), ).Run() } diff --git a/components/ledger/proto/account/account.pb.go b/components/ledger/proto/account/account.pb.go new file mode 100644 index 00000000..ecfd1de5 --- /dev/null +++ b/components/ledger/proto/account/account.pb.go @@ -0,0 +1,646 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.34.2 +// protoc v5.27.0 +// source: proto/account/account.proto + +package account + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type AccountID struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` +} + +func (x *AccountID) Reset() { + *x = AccountID{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_account_account_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *AccountID) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AccountID) ProtoMessage() {} + +func (x *AccountID) ProtoReflect() protoreflect.Message { + mi := &file_proto_account_account_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use AccountID.ProtoReflect.Descriptor instead. +func (*AccountID) Descriptor() ([]byte, []int) { + return file_proto_account_account_proto_rawDescGZIP(), []int{0} +} + +func (x *AccountID) GetId() string { + if x != nil { + return x.Id + } + return "" +} + +type AccountAlias struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Alias string `protobuf:"bytes,1,opt,name=alias,proto3" json:"alias,omitempty"` +} + +func (x *AccountAlias) Reset() { + *x = AccountAlias{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_account_account_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *AccountAlias) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AccountAlias) ProtoMessage() {} + +func (x *AccountAlias) ProtoReflect() protoreflect.Message { + mi := &file_proto_account_account_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use AccountAlias.ProtoReflect.Descriptor instead. +func (*AccountAlias) Descriptor() ([]byte, []int) { + return file_proto_account_account_proto_rawDescGZIP(), []int{1} +} + +func (x *AccountAlias) GetAlias() string { + if x != nil { + return x.Alias + } + return "" +} + +type Account struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + Alias string `protobuf:"bytes,2,opt,name=alias,proto3" json:"alias,omitempty"` + AvailableBalance float64 `protobuf:"fixed64,3,opt,name=available_balance,json=availableBalance,proto3" json:"available_balance,omitempty"` + OnHoldBalance float64 `protobuf:"fixed64,4,opt,name=on_hold_balance,json=onHoldBalance,proto3" json:"on_hold_balance,omitempty"` + BalanceScale float64 `protobuf:"fixed64,5,opt,name=balance_scale,json=balanceScale,proto3" json:"balance_scale,omitempty"` + AllowSending bool `protobuf:"varint,6,opt,name=allow_sending,json=allowSending,proto3" json:"allow_sending,omitempty"` + AllowReceiving bool `protobuf:"varint,7,opt,name=allow_receiving,json=allowReceiving,proto3" json:"allow_receiving,omitempty"` +} + +func (x *Account) Reset() { + *x = Account{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_account_account_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Account) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Account) ProtoMessage() {} + +func (x *Account) ProtoReflect() protoreflect.Message { + mi := &file_proto_account_account_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Account.ProtoReflect.Descriptor instead. +func (*Account) Descriptor() ([]byte, []int) { + return file_proto_account_account_proto_rawDescGZIP(), []int{2} +} + +func (x *Account) GetId() string { + if x != nil { + return x.Id + } + return "" +} + +func (x *Account) GetAlias() string { + if x != nil { + return x.Alias + } + return "" +} + +func (x *Account) GetAvailableBalance() float64 { + if x != nil { + return x.AvailableBalance + } + return 0 +} + +func (x *Account) GetOnHoldBalance() float64 { + if x != nil { + return x.OnHoldBalance + } + return 0 +} + +func (x *Account) GetBalanceScale() float64 { + if x != nil { + return x.BalanceScale + } + return 0 +} + +func (x *Account) GetAllowSending() bool { + if x != nil { + return x.AllowSending + } + return false +} + +func (x *Account) GetAllowReceiving() bool { + if x != nil { + return x.AllowReceiving + } + return false +} + +type UpdateRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` + Alias string `protobuf:"bytes,2,opt,name=alias,proto3" json:"alias,omitempty"` + AvailableBalance float64 `protobuf:"fixed64,3,opt,name=available_balance,json=availableBalance,proto3" json:"available_balance,omitempty"` + OnHoldBalance float64 `protobuf:"fixed64,4,opt,name=on_hold_balance,json=onHoldBalance,proto3" json:"on_hold_balance,omitempty"` + BalanceScale float64 `protobuf:"fixed64,5,opt,name=balance_scale,json=balanceScale,proto3" json:"balance_scale,omitempty"` +} + +func (x *UpdateRequest) Reset() { + *x = UpdateRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_account_account_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *UpdateRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UpdateRequest) ProtoMessage() {} + +func (x *UpdateRequest) ProtoReflect() protoreflect.Message { + mi := &file_proto_account_account_proto_msgTypes[3] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use UpdateRequest.ProtoReflect.Descriptor instead. +func (*UpdateRequest) Descriptor() ([]byte, []int) { + return file_proto_account_account_proto_rawDescGZIP(), []int{3} +} + +func (x *UpdateRequest) GetId() string { + if x != nil { + return x.Id + } + return "" +} + +func (x *UpdateRequest) GetAlias() string { + if x != nil { + return x.Alias + } + return "" +} + +func (x *UpdateRequest) GetAvailableBalance() float64 { + if x != nil { + return x.AvailableBalance + } + return 0 +} + +func (x *UpdateRequest) GetOnHoldBalance() float64 { + if x != nil { + return x.OnHoldBalance + } + return 0 +} + +func (x *UpdateRequest) GetBalanceScale() float64 { + if x != nil { + return x.BalanceScale + } + return 0 +} + +type ManyAccountsResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Accounts []*Account `protobuf:"bytes,1,rep,name=accounts,proto3" json:"accounts,omitempty"` +} + +func (x *ManyAccountsResponse) Reset() { + *x = ManyAccountsResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_account_account_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ManyAccountsResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ManyAccountsResponse) ProtoMessage() {} + +func (x *ManyAccountsResponse) ProtoReflect() protoreflect.Message { + mi := &file_proto_account_account_proto_msgTypes[4] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ManyAccountsResponse.ProtoReflect.Descriptor instead. +func (*ManyAccountsResponse) Descriptor() ([]byte, []int) { + return file_proto_account_account_proto_rawDescGZIP(), []int{4} +} + +func (x *ManyAccountsResponse) GetAccounts() []*Account { + if x != nil { + return x.Accounts + } + return nil +} + +type ManyAccountsID struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Ids []*AccountID `protobuf:"bytes,1,rep,name=ids,proto3" json:"ids,omitempty"` +} + +func (x *ManyAccountsID) Reset() { + *x = ManyAccountsID{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_account_account_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ManyAccountsID) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ManyAccountsID) ProtoMessage() {} + +func (x *ManyAccountsID) ProtoReflect() protoreflect.Message { + mi := &file_proto_account_account_proto_msgTypes[5] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ManyAccountsID.ProtoReflect.Descriptor instead. +func (*ManyAccountsID) Descriptor() ([]byte, []int) { + return file_proto_account_account_proto_rawDescGZIP(), []int{5} +} + +func (x *ManyAccountsID) GetIds() []*AccountID { + if x != nil { + return x.Ids + } + return nil +} + +type ManyAccountsAlias struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Aliases []*AccountAlias `protobuf:"bytes,1,rep,name=aliases,proto3" json:"aliases,omitempty"` +} + +func (x *ManyAccountsAlias) Reset() { + *x = ManyAccountsAlias{} + if protoimpl.UnsafeEnabled { + mi := &file_proto_account_account_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ManyAccountsAlias) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ManyAccountsAlias) ProtoMessage() {} + +func (x *ManyAccountsAlias) ProtoReflect() protoreflect.Message { + mi := &file_proto_account_account_proto_msgTypes[6] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ManyAccountsAlias.ProtoReflect.Descriptor instead. +func (*ManyAccountsAlias) Descriptor() ([]byte, []int) { + return file_proto_account_account_proto_rawDescGZIP(), []int{6} +} + +func (x *ManyAccountsAlias) GetAliases() []*AccountAlias { + if x != nil { + return x.Aliases + } + return nil +} + +var File_proto_account_account_proto protoreflect.FileDescriptor + +var file_proto_account_account_proto_rawDesc = []byte{ + 0x0a, 0x1b, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x2f, + 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x07, 0x61, + 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0x1b, 0x0a, 0x09, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, + 0x74, 0x49, 0x44, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x02, 0x69, 0x64, 0x22, 0x24, 0x0a, 0x0c, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x41, 0x6c, + 0x69, 0x61, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x05, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x22, 0xf7, 0x01, 0x0a, 0x07, 0x41, 0x63, + 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x12, 0x2b, 0x0a, 0x11, 0x61, + 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x01, 0x52, 0x10, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, + 0x65, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x26, 0x0a, 0x0f, 0x6f, 0x6e, 0x5f, 0x68, + 0x6f, 0x6c, 0x64, 0x5f, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x01, 0x52, 0x0d, 0x6f, 0x6e, 0x48, 0x6f, 0x6c, 0x64, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, + 0x12, 0x23, 0x0a, 0x0d, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x73, 0x63, 0x61, 0x6c, + 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x01, 0x52, 0x0c, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, + 0x53, 0x63, 0x61, 0x6c, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x5f, 0x73, + 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x61, 0x6c, + 0x6c, 0x6f, 0x77, 0x53, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x12, 0x27, 0x0a, 0x0f, 0x61, 0x6c, + 0x6c, 0x6f, 0x77, 0x5f, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x69, 0x6e, 0x67, 0x18, 0x07, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x0e, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x52, 0x65, 0x63, 0x65, 0x69, 0x76, + 0x69, 0x6e, 0x67, 0x22, 0xaf, 0x01, 0x0a, 0x0d, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x12, 0x2b, 0x0a, 0x11, 0x61, + 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x5f, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x01, 0x52, 0x10, 0x61, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, + 0x65, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x26, 0x0a, 0x0f, 0x6f, 0x6e, 0x5f, 0x68, + 0x6f, 0x6c, 0x64, 0x5f, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x01, 0x52, 0x0d, 0x6f, 0x6e, 0x48, 0x6f, 0x6c, 0x64, 0x42, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, + 0x12, 0x23, 0x0a, 0x0d, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x73, 0x63, 0x61, 0x6c, + 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x01, 0x52, 0x0c, 0x62, 0x61, 0x6c, 0x61, 0x6e, 0x63, 0x65, + 0x53, 0x63, 0x61, 0x6c, 0x65, 0x22, 0x44, 0x0a, 0x14, 0x4d, 0x61, 0x6e, 0x79, 0x41, 0x63, 0x63, + 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2c, 0x0a, + 0x08, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x10, 0x2e, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x2e, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, + 0x74, 0x52, 0x08, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x22, 0x36, 0x0a, 0x0e, 0x4d, + 0x61, 0x6e, 0x79, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x49, 0x44, 0x12, 0x24, 0x0a, + 0x03, 0x69, 0x64, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x61, 0x63, 0x63, + 0x6f, 0x75, 0x6e, 0x74, 0x2e, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x44, 0x52, 0x03, + 0x69, 0x64, 0x73, 0x22, 0x44, 0x0a, 0x11, 0x4d, 0x61, 0x6e, 0x79, 0x41, 0x63, 0x63, 0x6f, 0x75, + 0x6e, 0x74, 0x73, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x12, 0x2f, 0x0a, 0x07, 0x61, 0x6c, 0x69, 0x61, + 0x73, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x61, 0x63, 0x63, 0x6f, + 0x75, 0x6e, 0x74, 0x2e, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x41, 0x6c, 0x69, 0x61, 0x73, + 0x52, 0x07, 0x61, 0x6c, 0x69, 0x61, 0x73, 0x65, 0x73, 0x32, 0xd5, 0x01, 0x0a, 0x0c, 0x41, 0x63, + 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x44, 0x0a, 0x08, 0x47, 0x65, + 0x74, 0x42, 0x79, 0x49, 0x64, 0x73, 0x12, 0x17, 0x2e, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, + 0x2e, 0x4d, 0x61, 0x6e, 0x79, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x49, 0x44, 0x1a, + 0x1d, 0x2e, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x2e, 0x4d, 0x61, 0x6e, 0x79, 0x41, 0x63, + 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, + 0x12, 0x49, 0x0a, 0x0a, 0x47, 0x65, 0x74, 0x42, 0x79, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x12, 0x1a, + 0x2e, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x2e, 0x4d, 0x61, 0x6e, 0x79, 0x41, 0x63, 0x63, + 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x41, 0x6c, 0x69, 0x61, 0x73, 0x1a, 0x1d, 0x2e, 0x61, 0x63, 0x63, + 0x6f, 0x75, 0x6e, 0x74, 0x2e, 0x4d, 0x61, 0x6e, 0x79, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, + 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x34, 0x0a, 0x06, 0x55, + 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x16, 0x2e, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x2e, + 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x10, 0x2e, + 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x2e, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x22, + 0x00, 0x42, 0x0b, 0x5a, 0x09, 0x2e, 0x2f, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x62, 0x06, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_proto_account_account_proto_rawDescOnce sync.Once + file_proto_account_account_proto_rawDescData = file_proto_account_account_proto_rawDesc +) + +func file_proto_account_account_proto_rawDescGZIP() []byte { + file_proto_account_account_proto_rawDescOnce.Do(func() { + file_proto_account_account_proto_rawDescData = protoimpl.X.CompressGZIP(file_proto_account_account_proto_rawDescData) + }) + return file_proto_account_account_proto_rawDescData +} + +var file_proto_account_account_proto_msgTypes = make([]protoimpl.MessageInfo, 7) +var file_proto_account_account_proto_goTypes = []any{ + (*AccountID)(nil), // 0: account.AccountID + (*AccountAlias)(nil), // 1: account.AccountAlias + (*Account)(nil), // 2: account.Account + (*UpdateRequest)(nil), // 3: account.UpdateRequest + (*ManyAccountsResponse)(nil), // 4: account.ManyAccountsResponse + (*ManyAccountsID)(nil), // 5: account.ManyAccountsID + (*ManyAccountsAlias)(nil), // 6: account.ManyAccountsAlias +} +var file_proto_account_account_proto_depIdxs = []int32{ + 2, // 0: account.ManyAccountsResponse.accounts:type_name -> account.Account + 0, // 1: account.ManyAccountsID.ids:type_name -> account.AccountID + 1, // 2: account.ManyAccountsAlias.aliases:type_name -> account.AccountAlias + 5, // 3: account.AccountProto.GetByIds:input_type -> account.ManyAccountsID + 6, // 4: account.AccountProto.GetByAlias:input_type -> account.ManyAccountsAlias + 3, // 5: account.AccountProto.Update:input_type -> account.UpdateRequest + 4, // 6: account.AccountProto.GetByIds:output_type -> account.ManyAccountsResponse + 4, // 7: account.AccountProto.GetByAlias:output_type -> account.ManyAccountsResponse + 2, // 8: account.AccountProto.Update:output_type -> account.Account + 6, // [6:9] is the sub-list for method output_type + 3, // [3:6] is the sub-list for method input_type + 3, // [3:3] is the sub-list for extension type_name + 3, // [3:3] is the sub-list for extension extendee + 0, // [0:3] is the sub-list for field type_name +} + +func init() { file_proto_account_account_proto_init() } +func file_proto_account_account_proto_init() { + if File_proto_account_account_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_proto_account_account_proto_msgTypes[0].Exporter = func(v any, i int) any { + switch v := v.(*AccountID); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_account_account_proto_msgTypes[1].Exporter = func(v any, i int) any { + switch v := v.(*AccountAlias); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_account_account_proto_msgTypes[2].Exporter = func(v any, i int) any { + switch v := v.(*Account); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_account_account_proto_msgTypes[3].Exporter = func(v any, i int) any { + switch v := v.(*UpdateRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_account_account_proto_msgTypes[4].Exporter = func(v any, i int) any { + switch v := v.(*ManyAccountsResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_account_account_proto_msgTypes[5].Exporter = func(v any, i int) any { + switch v := v.(*ManyAccountsID); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_proto_account_account_proto_msgTypes[6].Exporter = func(v any, i int) any { + switch v := v.(*ManyAccountsAlias); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_proto_account_account_proto_rawDesc, + NumEnums: 0, + NumMessages: 7, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_proto_account_account_proto_goTypes, + DependencyIndexes: file_proto_account_account_proto_depIdxs, + MessageInfos: file_proto_account_account_proto_msgTypes, + }.Build() + File_proto_account_account_proto = out.File + file_proto_account_account_proto_rawDesc = nil + file_proto_account_account_proto_goTypes = nil + file_proto_account_account_proto_depIdxs = nil +} diff --git a/components/ledger/proto/account/account.proto b/components/ledger/proto/account/account.proto new file mode 100644 index 00000000..a5deda14 --- /dev/null +++ b/components/ledger/proto/account/account.proto @@ -0,0 +1,48 @@ +syntax = "proto3"; + +option go_package = "./account"; +package account; + +message AccountID { + string id = 1; +} + +message AccountAlias { + string alias = 1; +} + +message Account { + string id = 1; + string alias = 2; + double available_balance = 3; + double on_hold_balance = 4; + double balance_scale = 5; + bool allow_sending= 6; + bool allow_receiving = 7; +} + +message UpdateRequest { + string id = 1; + string alias = 2; + double available_balance = 3; + double on_hold_balance = 4; + double balance_scale = 5; +} + +message ManyAccountsResponse { + repeated Account accounts = 1; +} + +message ManyAccountsID { + repeated AccountID ids = 1; +} + +message ManyAccountsAlias { + repeated AccountAlias aliases = 1; +} + +service AccountProto { + rpc GetByIds(ManyAccountsID) returns (ManyAccountsResponse) {} + rpc GetByAlias(ManyAccountsAlias) returns (ManyAccountsResponse) {} + rpc Update(UpdateRequest) returns (Account) {} +} \ No newline at end of file diff --git a/components/ledger/proto/account/account_grpc.pb.go b/components/ledger/proto/account/account_grpc.pb.go new file mode 100644 index 00000000..601b97bd --- /dev/null +++ b/components/ledger/proto/account/account_grpc.pb.go @@ -0,0 +1,197 @@ +// Code generated by protoc-gen-go-grpc. DO NOT EDIT. +// versions: +// - protoc-gen-go-grpc v1.5.1 +// - protoc v5.27.0 +// source: proto/account/account.proto + +package account + +import ( + context "context" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" +) + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +// Requires gRPC-Go v1.64.0 or later. +const _ = grpc.SupportPackageIsVersion9 + +const ( + AccountProto_GetByIds_FullMethodName = "/account.AccountProto/GetByIds" + AccountProto_GetByAlias_FullMethodName = "/account.AccountProto/GetByAlias" + AccountProto_Update_FullMethodName = "/account.AccountProto/Update" +) + +// AccountProtoClient is the client API for AccountProto service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +type AccountProtoClient interface { + GetByIds(ctx context.Context, in *ManyAccountsID, opts ...grpc.CallOption) (*ManyAccountsResponse, error) + GetByAlias(ctx context.Context, in *ManyAccountsAlias, opts ...grpc.CallOption) (*ManyAccountsResponse, error) + Update(ctx context.Context, in *UpdateRequest, opts ...grpc.CallOption) (*Account, error) +} + +type accountProtoClient struct { + cc grpc.ClientConnInterface +} + +func NewAccountProtoClient(cc grpc.ClientConnInterface) AccountProtoClient { + return &accountProtoClient{cc} +} + +func (c *accountProtoClient) GetByIds(ctx context.Context, in *ManyAccountsID, opts ...grpc.CallOption) (*ManyAccountsResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(ManyAccountsResponse) + err := c.cc.Invoke(ctx, AccountProto_GetByIds_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *accountProtoClient) GetByAlias(ctx context.Context, in *ManyAccountsAlias, opts ...grpc.CallOption) (*ManyAccountsResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(ManyAccountsResponse) + err := c.cc.Invoke(ctx, AccountProto_GetByAlias_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *accountProtoClient) Update(ctx context.Context, in *UpdateRequest, opts ...grpc.CallOption) (*Account, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(Account) + err := c.cc.Invoke(ctx, AccountProto_Update_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +// AccountProtoServer is the server API for AccountProto service. +// All implementations must embed UnimplementedAccountProtoServer +// for forward compatibility. +type AccountProtoServer interface { + GetByIds(context.Context, *ManyAccountsID) (*ManyAccountsResponse, error) + GetByAlias(context.Context, *ManyAccountsAlias) (*ManyAccountsResponse, error) + Update(context.Context, *UpdateRequest) (*Account, error) + mustEmbedUnimplementedAccountProtoServer() +} + +// UnimplementedAccountProtoServer must be embedded to have +// forward compatible implementations. +// +// NOTE: this should be embedded by value instead of pointer to avoid a nil +// pointer dereference when methods are called. +type UnimplementedAccountProtoServer struct{} + +func (UnimplementedAccountProtoServer) GetByIds(context.Context, *ManyAccountsID) (*ManyAccountsResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetByIds not implemented") +} +func (UnimplementedAccountProtoServer) GetByAlias(context.Context, *ManyAccountsAlias) (*ManyAccountsResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method GetByAlias not implemented") +} +func (UnimplementedAccountProtoServer) Update(context.Context, *UpdateRequest) (*Account, error) { + return nil, status.Errorf(codes.Unimplemented, "method Update not implemented") +} +func (UnimplementedAccountProtoServer) mustEmbedUnimplementedAccountProtoServer() {} +func (UnimplementedAccountProtoServer) testEmbeddedByValue() {} + +// UnsafeAccountProtoServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to AccountProtoServer will +// result in compilation errors. +type UnsafeAccountProtoServer interface { + mustEmbedUnimplementedAccountProtoServer() +} + +func RegisterAccountProtoServer(s grpc.ServiceRegistrar, srv AccountProtoServer) { + // If the following call pancis, it indicates UnimplementedAccountProtoServer was + // embedded by pointer and is nil. This will cause panics if an + // unimplemented method is ever invoked, so we test this at initialization + // time to prevent it from happening at runtime later due to I/O. + if t, ok := srv.(interface{ testEmbeddedByValue() }); ok { + t.testEmbeddedByValue() + } + s.RegisterService(&AccountProto_ServiceDesc, srv) +} + +func _AccountProto_GetByIds_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ManyAccountsID) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(AccountProtoServer).GetByIds(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: AccountProto_GetByIds_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(AccountProtoServer).GetByIds(ctx, req.(*ManyAccountsID)) + } + return interceptor(ctx, in, info, handler) +} + +func _AccountProto_GetByAlias_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ManyAccountsAlias) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(AccountProtoServer).GetByAlias(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: AccountProto_GetByAlias_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(AccountProtoServer).GetByAlias(ctx, req.(*ManyAccountsAlias)) + } + return interceptor(ctx, in, info, handler) +} + +func _AccountProto_Update_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(UpdateRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(AccountProtoServer).Update(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: AccountProto_Update_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(AccountProtoServer).Update(ctx, req.(*UpdateRequest)) + } + return interceptor(ctx, in, info, handler) +} + +// AccountProto_ServiceDesc is the grpc.ServiceDesc for AccountProto service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var AccountProto_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "account.AccountProto", + HandlerType: (*AccountProtoServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "GetByIds", + Handler: _AccountProto_GetByIds_Handler, + }, + { + MethodName: "GetByAlias", + Handler: _AccountProto_GetByAlias_Handler, + }, + { + MethodName: "Update", + Handler: _AccountProto_Update_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "proto/account/account.proto", +} diff --git a/components/transaction/Makefile b/components/transaction/Makefile index 5ca93116..335cebaf 100644 --- a/components/transaction/Makefile +++ b/components/transaction/Makefile @@ -74,7 +74,7 @@ build: @docker-compose -f docker-compose.yml build up: - @docker-compose -f docker-compose.yml up + @docker-compose -f docker-compose.yml up -d start: @docker-compose -f docker-compose.yml start diff --git a/components/transaction/docker-compose.yml b/components/transaction/docker-compose.yml index da307c9f..558521f1 100644 --- a/components/transaction/docker-compose.yml +++ b/components/transaction/docker-compose.yml @@ -92,15 +92,17 @@ services: PGPASSWORD: ${REPLICATION_PASSWORD} command: | bash -c " - until pg_basebackup --pgdata=/var/lib/postgresql/data -R --slot=replication_slot --host=primary-transaction --port=${DB_PORT} - do - echo 'Waiting for primary-transaction to connect...' - sleep 3s - done - echo 'Backup done... starting replica-transaction...' - chmod 0700 /var/lib/postgresql/data - # Ensure the port is set to 5435 for the replica - sed -i 's/^#port.*/port = ${DB_REPLICA_PORT}/' /var/lib/postgresql/data/postgresql.conf + if [ ! -d \"/var/lib/postgresql/data\" ] || [ ! -f \"/var/lib/postgresql/data/postgresql.conf\" ]; then + until pg_basebackup --pgdata=/var/lib/postgresql/data -R --slot=replication_slot --host=primary-transaction --port=${DB_PORT} + do + echo 'Waiting for primary-transaction to connect...' + sleep 3s + done + echo 'Backup done... starting replica-transaction...' + chmod 0700 /var/lib/postgresql/data + # Ensure the port is set to 5435 for the replica + sed -i 's/^#port.*/port = ${DB_REPLICA_PORT}/' /var/lib/postgresql/data/postgresql.conf + fi exec postgres -c config_file=/var/lib/postgresql/data/postgresql.conf " healthcheck: diff --git a/go.mod b/go.mod index 0167ca82..ca2c7dc9 100644 --- a/go.mod +++ b/go.mod @@ -11,7 +11,7 @@ require ( github.com/go-playground/universal-translator v0.18.1 github.com/gofiber/fiber/v2 v2.52.5 github.com/gofiber/swagger v1.1.0 - github.com/jackc/pgx/v5 v5.6.0 + github.com/jackc/pgx/v5 v5.7.1 github.com/joho/godotenv v1.5.1 github.com/lib/pq v1.10.9 github.com/pkg/errors v0.9.1 @@ -20,6 +20,8 @@ require ( go.mongodb.org/mongo-driver v1.16.1 go.uber.org/mock v0.4.0 golang.org/x/oauth2 v0.23.0 + google.golang.org/grpc v1.64.0 + google.golang.org/protobuf v1.33.0 ) require ( @@ -31,7 +33,7 @@ require ( github.com/go-openapi/jsonreference v0.21.0 // indirect github.com/go-openapi/spec v0.21.0 // indirect github.com/go-openapi/swag v0.23.0 // indirect - github.com/jackc/puddle/v2 v2.2.1 // indirect + github.com/jackc/puddle/v2 v2.2.2 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 // indirect github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 // indirect @@ -44,7 +46,9 @@ require ( go.opentelemetry.io/otel v1.29.0 // indirect go.opentelemetry.io/otel/metric v1.29.0 // indirect go.opentelemetry.io/otel/trace v1.29.0 // indirect + golang.org/x/net v0.26.0 // indirect golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 // indirect ) require ( @@ -64,7 +68,7 @@ require ( github.com/hokaccha/go-prettyjson v0.0.0-20211117102719-0474bc63780f // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect - github.com/jackc/pgservicefile v0.0.0-20231201235250-de7065d80cb9 // indirect + github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect github.com/leodido/go-urn v1.2.4 // indirect github.com/lestrrat-go/backoff/v2 v2.0.8 // indirect github.com/lestrrat-go/blackmagic v1.0.2 // indirect @@ -83,10 +87,10 @@ require ( github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d // indirect go.uber.org/atomic v1.7.0 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/crypto v0.25.0 // indirect + golang.org/x/crypto v0.27.0 // indirect golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 // indirect golang.org/x/sync v0.8.0 // indirect - golang.org/x/term v0.22.0 // indirect + golang.org/x/term v0.24.0 // indirect golang.org/x/text v0.18.0 gopkg.in/go-playground/assert.v1 v1.2.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect @@ -118,6 +122,6 @@ require ( github.com/valyala/fasthttp v1.52.0 // indirect github.com/valyala/tcplisten v1.0.0 // indirect go.uber.org/zap v1.27.0 - golang.org/x/sys v0.22.0 // indirect + golang.org/x/sys v0.25.0 // indirect gopkg.in/go-playground/validator.v9 v9.31.0 ) diff --git a/go.sum b/go.sum index d39d40ea..391b26a1 100644 --- a/go.sum +++ b/go.sum @@ -124,12 +124,12 @@ github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2 github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= -github.com/jackc/pgservicefile v0.0.0-20231201235250-de7065d80cb9 h1:L0QtFUgDarD7Fpv9jeVMgy/+Ec0mtnmYuImjTz6dtDA= -github.com/jackc/pgservicefile v0.0.0-20231201235250-de7065d80cb9/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= -github.com/jackc/pgx/v5 v5.6.0 h1:SWJzexBzPL5jb0GEsrPMLIsi/3jOo7RHlzTjcAeDrPY= -github.com/jackc/pgx/v5 v5.6.0/go.mod h1:DNZ/vlrUnhWCoFGxHAG8U2ljioxukquj7utPDgtQdTw= -github.com/jackc/puddle/v2 v2.2.1 h1:RhxXJtFG022u4ibrCSMSiu5aOq1i77R3OHKNJj77OAk= -github.com/jackc/puddle/v2 v2.2.1/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4= +github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo= +github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= +github.com/jackc/pgx/v5 v5.7.1 h1:x7SYsPBYDkHDksogeSmZZ5xzThcTgRz++I5E+ePFUcs= +github.com/jackc/pgx/v5 v5.7.1/go.mod h1:e7O26IywZZ+naJtWWos6i6fvWK+29etgITqrqHLfoZA= +github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo= +github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4= github.com/jeremija/gosubmit v0.2.7 h1:At0OhGCFGPXyjPYAsCchoBUhE099pcBXmsb4iZqROIc= github.com/jeremija/gosubmit v0.2.7/go.mod h1:Ui+HS073lCFREXBbdfrJzMB57OI/bdxTiLtrDHHhFPI= github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= @@ -296,8 +296,8 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= -golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30= -golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M= +golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A= +golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70= golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 h1:vr/HnozRka3pE4EsMEg1lgkXJkTFJCVUX+S/ZT6wYzM= golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842/go.mod h1:XtvwrStGgqGPLc4cjQfWqZHG1YFdYs6swckp8vpsjnc= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= @@ -341,8 +341,8 @@ golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= -golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= +golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= @@ -351,8 +351,8 @@ golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY= -golang.org/x/term v0.22.0 h1:BbsgPEJULsl2fV/AT3v15Mjva5yXKQDyKf+TbDz7QJk= -golang.org/x/term v0.22.0/go.mod h1:F3qCibpT5AMpCRfhfT53vVJwhLtIVHhB9XDjfFvnMI4= +golang.org/x/term v0.24.0 h1:Mh5cbb+Zk2hqqXNO7S1iTjEphVL+jb8ZWaqh/g+JWkM= +golang.org/x/term v0.24.0/go.mod h1:lOBK/LVxemqiMij05LGJ0tzNr8xlmwBRJ81PX6wVLH8= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= @@ -372,6 +372,12 @@ golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg= golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 h1:NnYq6UN9ReLM9/Y01KWNOWyI5xQ9kbIms5GGJVwS/Yc= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237/go.mod h1:WtryC6hu0hhx87FDGxWCDptyssuo68sk10vYjF+T9fY= +google.golang.org/grpc v1.64.0 h1:KH3VH9y/MgNQg1dE7b3XfVK0GsPSIzJwdF617gUSbvY= +google.golang.org/grpc v1.64.0/go.mod h1:oxjF8E3FBnjp+/gVFYdWacaLDx9na1aqy9oovLpxQYg= +google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= +google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=