From e0fa44eef7ee9bbf973a0abf1e5a883a58e170b1 Mon Sep 17 00:00:00 2001 From: Bel LaPointe <153096461+breel-render@users.noreply.github.com> Date: Fri, 23 May 2025 20:32:49 -0600 Subject: [PATCH] test bank.cache --- src/bank/cache/cache.go | 88 ++++++++++++++++++++++++ src/bank/cache/cache_integration_test.go | 51 ++++++++++++++ src/bank/teller/teller.go | 10 ++- src/bank/types.go | 4 ++ 4 files changed, 152 insertions(+), 1 deletion(-) create mode 100644 src/bank/cache/cache.go create mode 100644 src/bank/cache/cache_integration_test.go diff --git a/src/bank/cache/cache.go b/src/bank/cache/cache.go new file mode 100644 index 0000000..0fef30e --- /dev/null +++ b/src/bank/cache/cache.go @@ -0,0 +1,88 @@ +package cache + +import ( + "context" + "encoding/json" + "fmt" + "os" + "path" + "time" + + "gogs.inhome.blapointe.com/ana-ledger/src/bank" +) + +type Client struct { + Client bank.Agg +} + +var _ bank.Agg = Client{} + +func New(client bank.Agg) Client { + return Client{Client: client} +} + +func (c Client) Accounts(ctx context.Context) ([]bank.Account, error) { + if result := []bank.Account{}; fromCache("accounts", &result) == nil { + return result, nil + } + + result, err := c.Client.Accounts(ctx) + if err != nil { + return nil, err + } + + toCache("accounts", result) + + return result, nil +} + +func (c Client) Transactions(ctx context.Context, a bank.Account) ([]bank.Transaction, error) { + if result := []bank.Transaction{}; fromCache(path.Join("accounts", a.Account), &result) == nil { + return result, nil + } + + result, err := c.Client.Transactions(ctx, a) + if err != nil { + return nil, err + } + + toCache(path.Join("accounts", a.Account), result) + + return result, nil +} + +var ( + d = path.Join("/tmp/ana_ledger_bank_cache.d") +) + +func toCache(k string, v interface{}) { + b, err := json.Marshal(v) + if err != nil { + return + } + + p := path.Join(d, k) + if err := os.WriteFile(p, b, os.ModePerm); err != nil { + os.Remove(p) + } +} + +func fromCache(k string, ptr interface{}) error { + p := path.Join(d, k) + if stat, err := os.Stat(p); err != nil { + return err + } else if time.Since(stat.ModTime()) > time.Hour { + return fmt.Errorf("stale") + } + + b, err := os.ReadFile(p) + if err != nil { + return err + } + + if err := json.Unmarshal(b, ptr); err != nil { + return err + } + + return nil +} diff --git a/src/bank/cache/cache_integration_test.go b/src/bank/cache/cache_integration_test.go new file mode 100644 index 0000000..c4ea099 --- /dev/null +++ b/src/bank/cache/cache_integration_test.go @@ -0,0 +1,51 @@ +//go:build integration + +package cache_test + +import ( + "context" + "strconv" + "testing" + + "gogs.inhome.blapointe.com/ana-ledger/src/bank/cache" + "gogs.inhome.blapointe.com/ana-ledger/src/bank/teller" +) + +func Test(t *testing.T) { + c, err := teller.New() + if err != nil { + t.Fatal(err) + } + + client := cache.New(c) + + ctx := context.Background() + + for i := 0; i < 2; i++ { + i := i + client := client + t.Run(strconv.Itoa(i), func(t *testing.T) { + accounts, err := c.Accounts(ctx) + if err != nil { + t.Fatal(err) + } + + for _, account := range accounts { + account := account + t.Run(account.Account, func(t *testing.T) { + transactions, err := c.Transactions(ctx, account) + if err != nil { + t.Fatal(err) + } + + for i, tr := range transactions { + t.Logf("[%d] %+v", i, tr) + } + }) + break + } + + }) + client.Client = nil + } +} diff --git a/src/bank/teller/teller.go b/src/bank/teller/teller.go index 1fc5cdd..503df25 100644 --- a/src/bank/teller/teller.go +++ b/src/bank/teller/teller.go @@ -3,6 +3,7 @@ package teller import ( "context" "crypto/tls" + _ "embed" "encoding/json" "net/http" "time" @@ -16,8 +17,15 @@ type Client struct { var _ bank.Agg = Client{} +var ( + //go:embed certificate.pem + certificate []byte + //go:embed private_key.pem + privateKey []byte +) + func New() (Client, error) { - cert, err := tls.LoadX509KeyPair("./certificate.pem", "./private_key.pem") // TODO + cert, err := tls.X509KeyPair(certificate, privateKey) return Client{cert: cert}, err } diff --git a/src/bank/types.go b/src/bank/types.go index d89771d..45132a5 100644 --- a/src/bank/types.go +++ b/src/bank/types.go @@ -1,6 +1,10 @@ package bank +import "context" + type Agg interface { + Accounts(context.Context) ([]Account, error) + Transactions(context.Context, Account) ([]Transaction, error) } type Account struct {