Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
gfyrag committed Nov 14, 2024
1 parent 889def0 commit fc2c1f6
Show file tree
Hide file tree
Showing 24 changed files with 316 additions and 399 deletions.
120 changes: 8 additions & 112 deletions internal/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,6 @@ import "github.com/formancehq/ledger/internal"
- [type ErrInvalidLedgerName](<#ErrInvalidLedgerName>)
- [func \(e ErrInvalidLedgerName\) Error\(\) string](<#ErrInvalidLedgerName.Error>)
- [func \(e ErrInvalidLedgerName\) Is\(err error\) bool](<#ErrInvalidLedgerName.Is>)
- [type FeatureSet](<#FeatureSet>)
- [func \(f FeatureSet\) Match\(features FeatureSet\) bool](<#FeatureSet.Match>)
- [func \(f FeatureSet\) SortedKeys\(\) \[\]string](<#FeatureSet.SortedKeys>)
- [func \(f FeatureSet\) String\(\) string](<#FeatureSet.String>)
- [func \(f FeatureSet\) With\(feature, value string\) FeatureSet](<#FeatureSet.With>)
- [type Ledger](<#Ledger>)
- [func MustNewWithDefault\(name string\) Ledger](<#MustNewWithDefault>)
- [func New\(name string, configuration Configuration\) \(\*Ledger, error\)](<#New>)
Expand Down Expand Up @@ -116,40 +111,20 @@ import "github.com/formancehq/ledger/internal"

## Constants

<a name="FeatureMovesHistory"></a>
<a name="MetaTargetTypeAccount"></a>

```go
const (
// FeatureMovesHistory is used to define if the ledger has to save funds movements history.
// Value is either ON or OFF
FeatureMovesHistory = "MOVES_HISTORY"
// FeatureMovesHistoryPostCommitEffectiveVolumes is used to define if the pvce property of funds movements history
// has to be updated with back dated transaction.
// Value is either SYNC or DISABLED.
// todo: depends on FeatureMovesHistory (dependency should be checked)
FeatureMovesHistoryPostCommitEffectiveVolumes = "MOVES_HISTORY_POST_COMMIT_EFFECTIVE_VOLUMES"
// FeatureHashLogs is used to defined it the logs has to be hashed.
FeatureHashLogs = "HASH_LOGS"
// FeatureAccountMetadataHistory is used to defined it the account metadata must be historized.
FeatureAccountMetadataHistory = "ACCOUNT_METADATA_HISTORY"
// FeatureTransactionMetadataHistory is used to defined it the transaction metadata must be historized.
FeatureTransactionMetadataHistory = "TRANSACTION_METADATA_HISTORY"
// FeatureIndexAddressSegments is used to defined it we want to index segments of accounts address.
// Without this feature, the ledger will not allow filtering on partial account address.
FeatureIndexAddressSegments = "INDEX_ADDRESS_SEGMENTS"
// FeatureIndexTransactionAccounts is used to defined it we want to index accounts used in a transaction.
FeatureIndexTransactionAccounts = "INDEX_TRANSACTION_ACCOUNTS"

DefaultBucket = "_default"
MetaTargetTypeAccount = "ACCOUNT"
MetaTargetTypeTransaction = "TRANSACTION"
)
```

<a name="MetaTargetTypeAccount"></a>
<a name="DefaultBucket"></a>

```go
const (
MetaTargetTypeAccount = "ACCOUNT"
MetaTargetTypeTransaction = "TRANSACTION"
DefaultBucket = "_default"
)
```

Expand All @@ -163,40 +138,6 @@ const (

## Variables

<a name="DefaultFeatures"></a>

```go
var (
DefaultFeatures = FeatureSet{
FeatureMovesHistory: "ON",
FeatureMovesHistoryPostCommitEffectiveVolumes: "SYNC",
FeatureHashLogs: "SYNC",
FeatureAccountMetadataHistory: "SYNC",
FeatureTransactionMetadataHistory: "SYNC",
FeatureIndexAddressSegments: "ON",
FeatureIndexTransactionAccounts: "ON",
}
MinimalFeatureSet = FeatureSet{
FeatureMovesHistory: "OFF",
FeatureMovesHistoryPostCommitEffectiveVolumes: "DISABLED",
FeatureHashLogs: "DISABLED",
FeatureAccountMetadataHistory: "DISABLED",
FeatureTransactionMetadataHistory: "DISABLED",
FeatureIndexAddressSegments: "OFF",
FeatureIndexTransactionAccounts: "OFF",
}
FeatureConfigurations = map[string][]string{
FeatureMovesHistory: {"ON", "OFF"},
FeatureMovesHistoryPostCommitEffectiveVolumes: {"SYNC", "DISABLED"},
FeatureHashLogs: {"SYNC", "DISABLED"},
FeatureAccountMetadataHistory: {"SYNC", "DISABLED"},
FeatureTransactionMetadataHistory: {"SYNC", "DISABLED"},
FeatureIndexAddressSegments: {"ON", "OFF"},
FeatureIndexTransactionAccounts: {"ON", "OFF"},
}
)
```

<a name="Zero"></a>

```go
Expand Down Expand Up @@ -281,9 +222,9 @@ type BalancesByAssetsByAccounts map[string]BalancesByAssets

```go
type Configuration struct {
Bucket string `json:"bucket" bun:"bucket,type:varchar(255)"`
Metadata metadata.Metadata `json:"metadata" bun:"metadata,type:jsonb"`
Features FeatureSet `json:"features" bun:"features,type:jsonb"`
Bucket string `json:"bucket" bun:"bucket,type:varchar(255)"`
Metadata metadata.Metadata `json:"metadata" bun:"metadata,type:jsonb"`
Features features.FeatureSet `json:"features" bun:"features,type:jsonb"`
}
```

Expand Down Expand Up @@ -433,51 +374,6 @@ func (e ErrInvalidLedgerName) Is(err error) bool



<a name="FeatureSet"></a>
## type FeatureSet



```go
type FeatureSet map[string]string
```

<a name="FeatureSet.Match"></a>
### func \(FeatureSet\) Match

```go
func (f FeatureSet) Match(features FeatureSet) bool
```



<a name="FeatureSet.SortedKeys"></a>
### func \(FeatureSet\) SortedKeys

```go
func (f FeatureSet) SortedKeys() []string
```



<a name="FeatureSet.String"></a>
### func \(FeatureSet\) String

```go
func (f FeatureSet) String() string
```



<a name="FeatureSet.With"></a>
### func \(FeatureSet\) With

```go
func (f FeatureSet) With(feature, value string) FeatureSet
```



<a name="Ledger"></a>
## type Ledger

Expand Down
3 changes: 2 additions & 1 deletion internal/controller/ledger/controller_default.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"database/sql"
"fmt"
"github.com/formancehq/ledger/pkg/features"
"math/big"
"reflect"

Expand Down Expand Up @@ -210,7 +211,7 @@ func (ctrl *DefaultController) importLog(ctx context.Context, sqlTx TX, log ledg
return fmt.Errorf("failed to insert log: %w", err)
}

if ctrl.ledger.HasFeature(ledger.FeatureHashLogs, "SYNC") {
if ctrl.ledger.HasFeature(features.FeatureHashLogs, "SYNC") {
if !reflect.DeepEqual(log.Hash, logCopy.Hash) {
return newErrInvalidHash(log.ID, logCopy.Hash, log.Hash)
}
Expand Down
3 changes: 2 additions & 1 deletion internal/controller/system/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package system

import (
"context"
"github.com/formancehq/ledger/pkg/features"
"reflect"
"time"

Expand Down Expand Up @@ -89,7 +90,7 @@ func (ctrl *DefaultController) CreateLedger(ctx context.Context, name string, co
configuration.SetDefaults()

if !ctrl.enableFeatures {
if !reflect.DeepEqual(configuration.Features, ledger.DefaultFeatures) {
if !reflect.DeepEqual(configuration.Features, features.DefaultFeatures) {
return ErrExperimentalFeaturesDisabled
}
}
Expand Down
129 changes: 9 additions & 120 deletions internal/ledger.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,12 @@ package ledger

import (
"fmt"
. "github.com/formancehq/go-libs/v2/collectionutils"
"github.com/formancehq/go-libs/v2/metadata"
"github.com/formancehq/go-libs/v2/time"
"github.com/formancehq/ledger/pkg/features"
"github.com/uptrace/bun"
"regexp"
"slices"
"strings"

"github.com/formancehq/go-libs/v2/metadata"
)

type Ledger struct {
Expand All @@ -22,7 +20,7 @@ type Ledger struct {
}

func (l Ledger) HasFeature(feature, value string) bool {
if err := validateFeatureWithValue(feature, value); err != nil {
if err := features.ValidateFeatureWithValue(feature, value); err != nil {
panic(err)
}

Expand Down Expand Up @@ -69,58 +67,10 @@ func MustNewWithDefault(name string) Ledger {
}

const (
// FeatureMovesHistory is used to define if the ledger has to save funds movements history.
// Value is either ON or OFF
FeatureMovesHistory = "MOVES_HISTORY"
// FeatureMovesHistoryPostCommitEffectiveVolumes is used to define if the pvce property of funds movements history
// has to be updated with back dated transaction.
// Value is either SYNC or DISABLED.
// todo: depends on FeatureMovesHistory (dependency should be checked)
FeatureMovesHistoryPostCommitEffectiveVolumes = "MOVES_HISTORY_POST_COMMIT_EFFECTIVE_VOLUMES"
// FeatureHashLogs is used to defined it the logs has to be hashed.
FeatureHashLogs = "HASH_LOGS"
// FeatureAccountMetadataHistory is used to defined it the account metadata must be historized.
FeatureAccountMetadataHistory = "ACCOUNT_METADATA_HISTORY"
// FeatureTransactionMetadataHistory is used to defined it the transaction metadata must be historized.
FeatureTransactionMetadataHistory = "TRANSACTION_METADATA_HISTORY"
// FeatureIndexAddressSegments is used to defined it we want to index segments of accounts address.
// Without this feature, the ledger will not allow filtering on partial account address.
FeatureIndexAddressSegments = "INDEX_ADDRESS_SEGMENTS"
// FeatureIndexTransactionAccounts is used to defined it we want to index accounts used in a transaction.
FeatureIndexTransactionAccounts = "INDEX_TRANSACTION_ACCOUNTS"

DefaultBucket = "_default"
)

var (
DefaultFeatures = FeatureSet{
FeatureMovesHistory: "ON",
FeatureMovesHistoryPostCommitEffectiveVolumes: "SYNC",
FeatureHashLogs: "SYNC",
FeatureAccountMetadataHistory: "SYNC",
FeatureTransactionMetadataHistory: "SYNC",
FeatureIndexAddressSegments: "ON",
FeatureIndexTransactionAccounts: "ON",
}
MinimalFeatureSet = FeatureSet{
FeatureMovesHistory: "OFF",
FeatureMovesHistoryPostCommitEffectiveVolumes: "DISABLED",
FeatureHashLogs: "DISABLED",
FeatureAccountMetadataHistory: "DISABLED",
FeatureTransactionMetadataHistory: "DISABLED",
FeatureIndexAddressSegments: "OFF",
FeatureIndexTransactionAccounts: "OFF",
}
FeatureConfigurations = map[string][]string{
FeatureMovesHistory: {"ON", "OFF"},
FeatureMovesHistoryPostCommitEffectiveVolumes: {"SYNC", "DISABLED"},
FeatureHashLogs: {"SYNC", "DISABLED"},
FeatureAccountMetadataHistory: {"SYNC", "DISABLED"},
FeatureTransactionMetadataHistory: {"SYNC", "DISABLED"},
FeatureIndexAddressSegments: {"ON", "OFF"},
FeatureIndexTransactionAccounts: {"ON", "OFF"},
}

ledgerNameFormat = regexp.MustCompile("^[0-9a-zA-Z_-]{1,63}$")
bucketNameFormat = regexp.MustCompile("^[0-9a-zA-Z_-]{1,63}$")

Expand All @@ -131,71 +81,10 @@ var (
"_healthcheck",
}
)

func validateFeatureWithValue(feature, value string) error {
possibleConfigurations, ok := FeatureConfigurations[feature]
if !ok {
return fmt.Errorf("feature %q not exists", feature)
}
if !slices.Contains(possibleConfigurations, value) {
return fmt.Errorf("configuration %s it not possible for feature %s", value, feature)
}

return nil
}

type FeatureSet map[string]string

func (f FeatureSet) With(feature, value string) FeatureSet {
ret := FeatureSet{}
for k, v := range f {
ret[k] = v
}
ret[feature] = value

return ret
}

func (f FeatureSet) SortedKeys() []string {
ret := Keys(f)
slices.Sort(ret)

return ret
}

func (f FeatureSet) String() string {
if len(f) == 0 {
return ""
}

ret := ""
for _, key := range f.SortedKeys() {
ret = ret + "," + shortenFeature(key) + "=" + f[key]
}

return ret[1:]
}

func (f FeatureSet) Match(features FeatureSet) bool {
for key, value := range features {
if f[key] != value {
return false
}
}

return true
}

func shortenFeature(feature string) string {
return strings.Join(Map(strings.Split(feature, "_"), func(from string) string {
return from[:1]
}), "")
}

type Configuration struct {
Bucket string `json:"bucket" bun:"bucket,type:varchar(255)"`
Metadata metadata.Metadata `json:"metadata" bun:"metadata,type:jsonb"`
Features FeatureSet `json:"features" bun:"features,type:jsonb"`
Bucket string `json:"bucket" bun:"bucket,type:varchar(255)"`
Metadata metadata.Metadata `json:"metadata" bun:"metadata,type:jsonb"`
Features features.FeatureSet `json:"features" bun:"features,type:jsonb"`
}

func (c *Configuration) SetDefaults() {
Expand All @@ -206,7 +95,7 @@ func (c *Configuration) SetDefaults() {
c.Features = map[string]string{}
}

for key, value := range DefaultFeatures {
for key, value := range features.DefaultFeatures {
if _, ok := c.Features[key]; !ok {
c.Features[key] = value
}
Expand All @@ -215,7 +104,7 @@ func (c *Configuration) SetDefaults() {

func (c *Configuration) Validate() error {
for feature, value := range c.Features {
if err := validateFeatureWithValue(feature, value); err != nil {
if err := features.ValidateFeatureWithValue(feature, value); err != nil {
return err
}
}
Expand All @@ -227,6 +116,6 @@ func NewDefaultConfiguration() Configuration {
return Configuration{
Bucket: DefaultBucket,
Metadata: metadata.Metadata{},
Features: DefaultFeatures,
Features: features.DefaultFeatures,
}
}
5 changes: 3 additions & 2 deletions internal/ledger_test.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
package ledger

import (
"github.com/formancehq/ledger/pkg/features"
"github.com/stretchr/testify/require"
"testing"
)

func TestFeatures(t *testing.T) {
f := MinimalFeatureSet.With(FeatureMovesHistory, "DISABLED")
require.Equal(t, "DISABLED", f[FeatureMovesHistory])
f := features.MinimalFeatureSet.With(features.FeatureMovesHistory, "DISABLED")
require.Equal(t, "DISABLED", f[features.FeatureMovesHistory])
require.Equal(t, "AMH=DISABLED,HL=DISABLED,IAS=OFF,ITA=OFF,MH=DISABLED,MHPCEV=DISABLED,TMH=DISABLED", f.String())
}
Loading

0 comments on commit fc2c1f6

Please sign in to comment.