Skip to content

Commit

Permalink
Add persistence.
Browse files Browse the repository at this point in the history
Adds some basic persistence using a yml file for now. Eventually I'll
swap this out for "proper" KV storage connection.
  • Loading branch information
samshadwell committed Nov 19, 2023
1 parent d6e2810 commit 5c25ad6
Show file tree
Hide file tree
Showing 4 changed files with 123 additions and 4 deletions.
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,7 @@
go.work

# Sensitive config
config.yml
config.yml

# Simple local KV store
storage.yml
24 changes: 21 additions & 3 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"net/http"
"os"

"github.com/samshadwell/split-ynab/storage"
"github.com/samshadwell/split-ynab/ynab"
)

Expand All @@ -24,13 +25,30 @@ func main() {
os.Exit(1)
}

budgetsResponse, err := client.GetBudgetsWithResponse(context.TODO(), &ynab.GetBudgetsParams{})
storage := storage.NewLocalStorageAdapter()
// Ignore error return, we can use the default value of 0 in case of error.
serverKnowledge, _ := storage.GetLastServerKnowledge(config.BudgetId)

transactionsResponse, err := client.GetTransactionsByAccountWithResponse(
context.TODO(),
config.BudgetId,
config.SplitAccountIds[0],
&ynab.GetTransactionsByAccountParams{
LastKnowledgeOfServer: &serverKnowledge,
},
)
if err != nil {
fmt.Fprintf(os.Stderr, "Error while getting budgets: %v\n", err)
fmt.Fprintf(os.Stderr, "Error while getting transactions: %v\n", err)
os.Exit(1)
}

fmt.Printf("Budgets: %v\n", budgetsResponse.JSON200.Data.Budgets)
newKnowledge := transactionsResponse.JSON200.Data.ServerKnowledge
fmt.Printf("Transaction count: %v, New server knowledge: %v\n", len(transactionsResponse.JSON200.Data.Transactions), newKnowledge)
err = storage.SetLastServerKnowledge(config.BudgetId, newKnowledge)
if err != nil {
fmt.Fprintf(os.Stderr, "Error while setting new server knowledge: %v\n", err)
os.Exit(1)
}
}

func constructClient(authToken string) (*ynab.ClientWithResponses, error) {
Expand Down
92 changes: 92 additions & 0 deletions storage/file_storage_adapter.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
package storage

import (
"fmt"
"os"

"gopkg.in/yaml.v3"
)

type localStorageAdapter struct{}

const storageFile = "storage.yml"

type budgetData struct {
BudgetId string `yaml:"budgetId"`
LastServerKnowledge int64 `yaml:"lastServerKnowledge"`
}

// Creates a StorageAdapter which stores data in a yaml file. Intended mostly for prototyping or running in environments
// without "proper" KV storage mechanisms.
func NewLocalStorageAdapter() StorageAdapter {
return &localStorageAdapter{}
}

func (l *localStorageAdapter) GetLastServerKnowledge(budgetId string) (int64, error) {
data, err := l.readData(budgetId)
if err != nil {
return 0, err
}

for _, d := range data {
if d.BudgetId == budgetId {
return d.LastServerKnowledge, nil
}
}

return 0, fmt.Errorf("No budget found with id %v", budgetId)
}

func (l *localStorageAdapter) SetLastServerKnowledge(budgetId string, serverKnowledge int64) error {
var data []budgetData

if _, err := os.Stat(storageFile); err == nil {
data, err = l.readData(budgetId)
if err != nil {
return err
}
}

found := false
for i, d := range data {
if d.BudgetId == budgetId {
data[i].LastServerKnowledge = serverKnowledge
found = true
break
}
}
if !found {
data = append(data, budgetData{
BudgetId: budgetId,
LastServerKnowledge: serverKnowledge,
})
}

f, err := os.Create(storageFile)
if err != nil {
return err
}
defer f.Close()

encoder := yaml.NewEncoder(f)
defer encoder.Close()

return encoder.Encode(data)
}

func (l *localStorageAdapter) readData(budgetId string) ([]budgetData, error) {
f, err := os.Open(storageFile)
if err != nil {
return nil, err
}
defer f.Close()

var data []budgetData
decoder := yaml.NewDecoder(f)
err = decoder.Decode(&data)
if err != nil {
return nil, err
}

return data, nil
}
6 changes: 6 additions & 0 deletions storage/storage_adapter.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package storage

type StorageAdapter interface {
GetLastServerKnowledge(budgetId string) (int64, error)
SetLastServerKnowledge(budgetId string, serverKnowledge int64) error
}

0 comments on commit 5c25ad6

Please sign in to comment.