Skip to content

Commit

Permalink
feat: add persistent on-disk cache (#74)
Browse files Browse the repository at this point in the history
* feat: add persistent on-file cache

* chore: pass filesystem to cache

* fix: reorder create mute callback data

* chore: fixed tests

* chore: add fs.WriteFile tests

* chore: add cache load/save tests

* chore: forgot to commit
  • Loading branch information
freak12techno authored Dec 17, 2024
1 parent bd33a64 commit def8aa9
Show file tree
Hide file tree
Showing 26 changed files with 244 additions and 108 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ dist/
grafana-interacter
**/.DS_Store
cover.out
cache.json
1 change: 1 addition & 0 deletions assets/cache.json
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"710cf772":"alertname=SlinkyHealthcheckTickerUpdateFailed datacenter=home host=neutron-testnet hosting=proxmox-2 id=rndr/usd instance=1.2.3.4:8002 job=slinky network=neutron severity=warning type=testnet","bb256a09":"alertname=MissedBlocksCheckerNoNewEventsFromNode chain=bitsong host=monitoring instance=localhost:9570 job=missed-blocks-checker node=https://rpc.example.com:443 severity=warning"}
2 changes: 1 addition & 1 deletion cmd/grafana-interacter.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ func ExecuteMain(configPath string) {
logger.GetDefaultLogger().Panic().Err(err).Msg("Error validating config")
}

newApp := app.NewApp(config, version)
newApp := app.NewApp(config, filesystem, version)
newApp.Start()
}

Expand Down
11 changes: 10 additions & 1 deletion config.example.yml
Original file line number Diff line number Diff line change
@@ -1,13 +1,22 @@
# Timezone. Used when displaying dates (like in silences and alerts).
# Defaults to "Etc/GMT" (so GMT+0)
timezone: "Europe/Moscow"
# So, Telegram has its own limitations - every button has a "data" field, which we use
# to pass some data to next callbacks, and it's limited to 64 bytes
# (see https://core.telegram.org/bots/api#inlinekeyboardbutton). We use cache on our side
# to be able to fit into these limits. This cache may work as in-memory only cache,
# or be persistent to file. This param specifies the path to this cache file; if it's not present,
# the cache will be not persistent if the app is restarted, so you might face issues
# if you start an app, do some queries, restart the app then try to press the buttons
# that were generated before restarting the app.
cache-path: "cache.json"
# Logging configuration.
log:
# Log level. Defaults to "info"
level: info
# Output logs as JSON. Useful if you are using logging aggregation solutions such as ELK. Defaults to false.
json: false
# Telegram bot token, you can create a Telegam bot with @BotFather bot on Telegram
# Telegram bot token, you can create a Telegram bot with @BotFather bot on Telegram
telegram:
token: xxx:yyy
# List of Telegram user IDs who can interact with the bot.
Expand Down
11 changes: 6 additions & 5 deletions pkg/app/alert_show_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"errors"
"main/assets"
configPkg "main/pkg/config"
"main/pkg/fs"
"main/pkg/types"
"main/pkg/types/render"
"testing"
Expand Down Expand Up @@ -41,7 +42,7 @@ func TestAppShowAlertInvalidInvocation(t *testing.T) {
httpmock.NewBytesResponder(200, assets.GetBytesOrPanic("telegram-send-message-ok.json")),
)

app := NewApp(config, "1.2.3")
app := NewApp(config, &fs.TestFS{}, "1.2.3")
ctx := app.Bot.NewContext(tele.Update{
ID: 1,
Message: &tele.Message{
Expand Down Expand Up @@ -86,7 +87,7 @@ func TestAppShowAlertFailedToFetchAlerts(t *testing.T) {
httpmock.NewBytesResponder(200, assets.GetBytesOrPanic("telegram-send-message-ok.json")),
)

app := NewApp(config, "1.2.3")
app := NewApp(config, &fs.TestFS{}, "1.2.3")
ctx := app.Bot.NewContext(tele.Update{
ID: 1,
Message: &tele.Message{
Expand Down Expand Up @@ -131,7 +132,7 @@ func TestAppShowAlertRuleNotFound(t *testing.T) {
httpmock.NewBytesResponder(200, assets.GetBytesOrPanic("telegram-send-message-ok.json")),
)

app := NewApp(config, "1.2.3")
app := NewApp(config, &fs.TestFS{}, "1.2.3")
ctx := app.Bot.NewContext(tele.Update{
ID: 1,
Message: &tele.Message{
Expand Down Expand Up @@ -175,7 +176,7 @@ func TestAppShowAlertRuleOk(t *testing.T) {
httpmock.NewBytesResponder(200, assets.GetBytesOrPanic("telegram-send-message-ok.json")),
)

app := NewApp(config, "1.2.3")
app := NewApp(config, &fs.TestFS{}, "1.2.3")
ctx := app.Bot.NewContext(tele.Update{
ID: 1,
Message: &tele.Message{
Expand Down Expand Up @@ -220,7 +221,7 @@ func TestAppShowAlertRenderOk(t *testing.T) {
httpmock.NewBytesResponder(200, assets.GetBytesOrPanic("telegram-send-message-ok.json")),
)

app := NewApp(config, "1.2.3")
app := NewApp(config, &fs.TestFS{}, "1.2.3")
ctx := app.Bot.NewContext(tele.Update{
ID: 1,
Message: &tele.Message{
Expand Down
19 changes: 10 additions & 9 deletions pkg/app/alerts_firing_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"main/assets"
configPkg "main/pkg/config"
"main/pkg/constants"
"main/pkg/fs"
"main/pkg/types"
"main/pkg/types/render"
"testing"
Expand Down Expand Up @@ -46,7 +47,7 @@ func TestAppFiringAlertsNoAlertSources(t *testing.T) {
httpmock.NewBytesResponder(200, assets.GetBytesOrPanic("telegram-send-message-ok.json")),
)

app := NewApp(config, "1.2.3")
app := NewApp(config, &fs.TestFS{}, "1.2.3")
ctx := app.Bot.NewContext(tele.Update{
ID: 1,
Message: &tele.Message{
Expand Down Expand Up @@ -106,7 +107,7 @@ func TestAppFiringAlertsMultipleAlertSources(t *testing.T) {
httpmock.NewBytesResponder(200, assets.GetBytesOrPanic("telegram-send-message-ok.json")),
)

app := NewApp(config, "1.2.3")
app := NewApp(config, &fs.TestFS{}, "1.2.3")
ctx := app.Bot.NewContext(tele.Update{
ID: 1,
Message: &tele.Message{
Expand Down Expand Up @@ -151,7 +152,7 @@ func TestAppFiringAlertsAlertSourceFail(t *testing.T) {
httpmock.NewBytesResponder(200, assets.GetBytesOrPanic("telegram-send-message-ok.json")),
)

app := NewApp(config, "1.2.3")
app := NewApp(config, &fs.TestFS{}, "1.2.3")
ctx := app.Bot.NewContext(tele.Update{
ID: 1,
Message: &tele.Message{
Expand Down Expand Up @@ -195,7 +196,7 @@ func TestAppFiringAlertsAlertLastPage(t *testing.T) {
httpmock.NewBytesResponder(200, assets.GetBytesOrPanic("telegram-send-message-ok.json")),
)

app := NewApp(config, "1.2.3")
app := NewApp(config, &fs.TestFS{}, "1.2.3")
ctx := app.Bot.NewContext(tele.Update{
ID: 1,
Message: &tele.Message{
Expand Down Expand Up @@ -253,7 +254,7 @@ func TestAppAlertsFiringRenderOk(t *testing.T) {
httpmock.NewBytesResponder(200, assets.GetBytesOrPanic("telegram-send-message-ok.json")),
)

app := NewApp(config, "1.2.3")
app := NewApp(config, &fs.TestFS{}, "1.2.3")
ctx := app.Bot.NewContext(tele.Update{
ID: 1,
Message: &tele.Message{
Expand Down Expand Up @@ -328,7 +329,7 @@ func TestAppFiringAlertsAlertFirstPage(t *testing.T) {
httpmock.NewBytesResponder(200, assets.GetBytesOrPanic("telegram-send-message-ok.json")),
)

app := NewApp(config, "1.2.3")
app := NewApp(config, &fs.TestFS{}, "1.2.3")
ctx := app.Bot.NewContext(tele.Update{
ID: 1,
Message: &tele.Message{
Expand Down Expand Up @@ -368,7 +369,7 @@ func TestAppFiringAlertsAlertInvalidCallback(t *testing.T) {
httpmock.NewBytesResponder(200, assets.GetBytesOrPanic("telegram-send-message-ok.json")),
)

app := NewApp(config, "1.2.3")
app := NewApp(config, &fs.TestFS{}, "1.2.3")
ctx := app.Bot.NewContext(tele.Update{
ID: 1,
Message: &tele.Message{
Expand Down Expand Up @@ -421,7 +422,7 @@ func TestAppFiringAlertsAlertAlertSourceDisabled(t *testing.T) {
httpmock.NewBytesResponder(200, assets.GetBytesOrPanic("telegram-send-message-ok.json")),
)

app := NewApp(config, "1.2.3")
app := NewApp(config, &fs.TestFS{}, "1.2.3")
ctx := app.Bot.NewContext(tele.Update{
ID: 1,
Message: &tele.Message{
Expand Down Expand Up @@ -479,7 +480,7 @@ func TestAppFiringAlertsAlertNoAlerts(t *testing.T) {
httpmock.NewBytesResponder(200, assets.GetBytesOrPanic("telegram-send-message-ok.json")),
)

app := NewApp(config, "1.2.3")
app := NewApp(config, &fs.TestFS{}, "1.2.3")
ctx := app.Bot.NewContext(tele.Update{
ID: 1,
Message: &tele.Message{
Expand Down
7 changes: 4 additions & 3 deletions pkg/app/alerts_list_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"errors"
"main/assets"
configPkg "main/pkg/config"
"main/pkg/fs"
"main/pkg/types"
"testing"

Expand Down Expand Up @@ -42,7 +43,7 @@ func TestAppListAlertsNoAlertSources(t *testing.T) {
httpmock.NewBytesResponder(200, assets.GetBytesOrPanic("telegram-send-message-ok.json")),
)

app := NewApp(config, "1.2.3")
app := NewApp(config, &fs.TestFS{}, "1.2.3")
ctx := app.Bot.NewContext(tele.Update{
ID: 1,
Message: &tele.Message{
Expand Down Expand Up @@ -90,7 +91,7 @@ func TestAppListAlertsAlertSourceFail(t *testing.T) {
httpmock.NewBytesResponder(200, assets.GetBytesOrPanic("telegram-send-message-ok.json")),
)

app := NewApp(config, "1.2.3")
app := NewApp(config, &fs.TestFS{}, "1.2.3")
ctx := app.Bot.NewContext(tele.Update{
ID: 1,
Message: &tele.Message{
Expand Down Expand Up @@ -143,7 +144,7 @@ func TestAppListAlertsOk(t *testing.T) {
httpmock.NewBytesResponder(200, assets.GetBytesOrPanic("telegram-send-message-ok.json")),
)

app := NewApp(config, "1.2.3")
app := NewApp(config, &fs.TestFS{}, "1.2.3")
ctx := app.Bot.NewContext(tele.Update{
ID: 1,
Message: &tele.Message{
Expand Down
7 changes: 5 additions & 2 deletions pkg/app/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"main/pkg/clients"
configPkg "main/pkg/config"
"main/pkg/constants"
"main/pkg/fs"
loggerPkg "main/pkg/logger"
"main/pkg/silence_manager"
"main/pkg/templates"
Expand Down Expand Up @@ -39,7 +40,7 @@ type App struct {
StopChannel chan bool
}

func NewApp(config *configPkg.Config, version string) *App {
func NewApp(config *configPkg.Config, filesystem fs.FS, version string) *App {
timezone, _ := time.LoadLocation(config.Timezone)

logger := loggerPkg.GetLogger(config.Log)
Expand Down Expand Up @@ -83,12 +84,14 @@ func NewApp(config *configPkg.Config, version string) *App {
AlertSourcesWithSilenceManager: alertSourcesWithSilenceManagers,
Bot: bot,
Version: version,
Cache: cache.NewCache(logger),
Cache: cache.NewCache(logger, filesystem, config.CachePath),
StopChannel: make(chan bool),
}
}

func (a *App) Start() {
a.Cache.Load()

// Commands
a.Bot.Handle("/start", a.HandleHelp)
a.Bot.Handle("/help", a.HandleHelp)
Expand Down
9 changes: 5 additions & 4 deletions pkg/app/app_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"errors"
"main/assets"
configPkg "main/pkg/config"
"main/pkg/fs"
"strings"
"sync"
"testing"
Expand Down Expand Up @@ -34,7 +35,7 @@ func TestAppCannotFetchBot(t *testing.T) {
Prometheus: nil,
}

app := NewApp(config, "1.2.3")
app := NewApp(config, &fs.TestFS{}, "1.2.3")
app.Start()
}

Expand All @@ -57,7 +58,7 @@ func TestAppStartsOkay(t *testing.T) {
"https://api.telegram.org/botxxx:yyy/getMe",
httpmock.NewBytesResponder(200, assets.GetBytesOrPanic("telegram-bot-ok.json")))

app := NewApp(config, "1.2.3")
app := NewApp(config, &fs.TestFS{}, "1.2.3")
var wg sync.WaitGroup
wg.Add(1)

Expand Down Expand Up @@ -104,7 +105,7 @@ func TestAppBotSendMultilineFail(t *testing.T) {
"https://api.telegram.org/botxxx:yyy/sendMessage",
httpmock.NewErrorResponder(errors.New("custom error")))

app := NewApp(config, "1.2.3")
app := NewApp(config, &fs.TestFS{}, "1.2.3")
ctx := app.Bot.NewContext(tele.Update{
ID: 1,
Message: &tele.Message{
Expand Down Expand Up @@ -145,7 +146,7 @@ func TestAppBotSendMultilineOk(t *testing.T) {
"https://api.telegram.org/botxxx:yyy/sendMessage",
httpmock.NewBytesResponder(200, assets.GetBytesOrPanic("telegram-send-message-ok.json")))

app := NewApp(config, "1.2.3")
app := NewApp(config, &fs.TestFS{}, "1.2.3")
ctx := app.Bot.NewContext(tele.Update{
ID: 1,
Message: &tele.Message{
Expand Down
5 changes: 3 additions & 2 deletions pkg/app/dashboards_list_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"errors"
"main/assets"
configPkg "main/pkg/config"
"main/pkg/fs"
"main/pkg/types"
"testing"

Expand Down Expand Up @@ -43,7 +44,7 @@ func TestAppDashboardListFailedToFetch(t *testing.T) {
httpmock.NewBytesResponder(200, assets.GetBytesOrPanic("telegram-send-message-ok.json")),
)

app := NewApp(config, "1.2.3")
app := NewApp(config, &fs.TestFS{}, "1.2.3")
ctx := app.Bot.NewContext(tele.Update{
ID: 1,
Message: &tele.Message{
Expand Down Expand Up @@ -88,7 +89,7 @@ func TestAppDashboardListOk(t *testing.T) {
httpmock.NewBytesResponder(200, assets.GetBytesOrPanic("telegram-send-message-ok.json")),
)

app := NewApp(config, "1.2.3")
app := NewApp(config, &fs.TestFS{}, "1.2.3")
ctx := app.Bot.NewContext(tele.Update{
ID: 1,
Message: &tele.Message{
Expand Down
11 changes: 6 additions & 5 deletions pkg/app/dashboards_show_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"errors"
"main/assets"
configPkg "main/pkg/config"
"main/pkg/fs"
"main/pkg/types"
"testing"

Expand Down Expand Up @@ -38,7 +39,7 @@ func TestAppShowDashboardInvalidInvocation(t *testing.T) {
httpmock.NewBytesResponder(200, assets.GetBytesOrPanic("telegram-send-message-ok.json")),
)

app := NewApp(config, "1.2.3")
app := NewApp(config, &fs.TestFS{}, "1.2.3")
ctx := app.Bot.NewContext(tele.Update{
ID: 1,
Message: &tele.Message{
Expand Down Expand Up @@ -83,7 +84,7 @@ func TestAppShowDashboardDashboardsListFail(t *testing.T) {
httpmock.NewBytesResponder(200, assets.GetBytesOrPanic("telegram-send-message-ok.json")),
)

app := NewApp(config, "1.2.3")
app := NewApp(config, &fs.TestFS{}, "1.2.3")
ctx := app.Bot.NewContext(tele.Update{
ID: 1,
Message: &tele.Message{
Expand Down Expand Up @@ -128,7 +129,7 @@ func TestAppShowDashboardDashboardNotFound(t *testing.T) {
httpmock.NewBytesResponder(200, assets.GetBytesOrPanic("telegram-send-message-ok.json")),
)

app := NewApp(config, "1.2.3")
app := NewApp(config, &fs.TestFS{}, "1.2.3")
ctx := app.Bot.NewContext(tele.Update{
ID: 1,
Message: &tele.Message{
Expand Down Expand Up @@ -178,7 +179,7 @@ func TestAppShowDashboardDashboardFetchError(t *testing.T) {
httpmock.NewBytesResponder(200, assets.GetBytesOrPanic("telegram-send-message-ok.json")),
)

app := NewApp(config, "1.2.3")
app := NewApp(config, &fs.TestFS{}, "1.2.3")
ctx := app.Bot.NewContext(tele.Update{
ID: 1,
Message: &tele.Message{
Expand Down Expand Up @@ -228,7 +229,7 @@ func TestAppShowDashboardOk(t *testing.T) {
httpmock.NewBytesResponder(200, assets.GetBytesOrPanic("telegram-send-message-ok.json")),
)

app := NewApp(config, "1.2.3")
app := NewApp(config, &fs.TestFS{}, "1.2.3")
ctx := app.Bot.NewContext(tele.Update{
ID: 1,
Message: &tele.Message{
Expand Down
5 changes: 3 additions & 2 deletions pkg/app/datasource_list_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"errors"
"main/assets"
configPkg "main/pkg/config"
"main/pkg/fs"
"main/pkg/types"
"testing"

Expand Down Expand Up @@ -43,7 +44,7 @@ func TestAppDatasourceListFailedToFetch(t *testing.T) {
httpmock.NewBytesResponder(200, assets.GetBytesOrPanic("telegram-send-message-ok.json")),
)

app := NewApp(config, "1.2.3")
app := NewApp(config, &fs.TestFS{}, "1.2.3")
ctx := app.Bot.NewContext(tele.Update{
ID: 1,
Message: &tele.Message{
Expand Down Expand Up @@ -88,7 +89,7 @@ func TestAppDatasourceListOk(t *testing.T) {
httpmock.NewBytesResponder(200, assets.GetBytesOrPanic("telegram-send-message-ok.json")),
)

app := NewApp(config, "1.2.3")
app := NewApp(config, &fs.TestFS{}, "1.2.3")
ctx := app.Bot.NewContext(tele.Update{
ID: 1,
Message: &tele.Message{
Expand Down
Loading

0 comments on commit def8aa9

Please sign in to comment.