Skip to content

Commit

Permalink
feat(manager): force strategy (#107)
Browse files Browse the repository at this point in the history
  • Loading branch information
nobe4 authored Jul 20, 2024
1 parent 1b282ad commit 526ced0
Show file tree
Hide file tree
Showing 8 changed files with 283 additions and 113 deletions.
12 changes: 9 additions & 3 deletions internal/cmd/sync.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ var (
noop bool
force bool
notificationDumpPath string
refreshStrategy managerPkg.RefreshStrategy

refreshStrategy managerPkg.RefreshStrategy
forceStrategy managerPkg.ForceStrategy

syncCmd = &cobra.Command{
Use: "sync",
Expand All @@ -34,8 +36,10 @@ func init() {
rootCmd.AddCommand(syncCmd)

syncCmd.Flags().BoolVarP(&noop, "noop", "n", false, "Doesn't execute any action")
syncCmd.Flags().BoolVarP(&force, "force", "f", false, "Force the execution of the rules on Done notifications")

syncCmd.Flags().VarP(&forceStrategy, "force-strategy", "f", fmt.Sprintf("Force strategy: %s", forceStrategy.Allowed()))
syncCmd.Flags().VarP(&refreshStrategy, "refresh-strategy", "r", fmt.Sprintf("Refresh strategy: %s", refreshStrategy.Allowed()))

syncCmd.Flags().StringVarP(&notificationDumpPath, "from-file", "", "", "Path to notification dump in JSON (generate with 'gh api /notifications')")
}

Expand All @@ -52,7 +56,9 @@ func runSync(cmd *cobra.Command, args []string) error {
return err
}
}
manager.WithRefresh(refreshStrategy).WithCaller(caller)
manager.Force = forceStrategy
manager.Refresh = refreshStrategy
manager.WithCaller(caller)

if err := manager.Load(); err != nil {
slog.Error("Failed to load the notifications", "err", err)
Expand Down
4 changes: 2 additions & 2 deletions internal/gh/enrichments.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ type Extra struct {
HtmlUrl string `json:"html_url"`
}

func (c *Client) enrichNotification(n *notifications.Notification) error {
if n.Meta.Done {
func (c *Client) Enrich(n *notifications.Notification) error {
if n == nil {
return nil
}

Expand Down
12 changes: 0 additions & 12 deletions internal/gh/gh.go
Original file line number Diff line number Diff line change
Expand Up @@ -144,18 +144,6 @@ func (c *Client) paginate() (notifications.Notifications, error) {
return list, nil
}

func (c *Client) Enrich(ns notifications.Notifications) (notifications.Notifications, error) {
for i, n := range ns {
if err := c.enrichNotification(n); err != nil {
return nil, err
}

ns[i] = n
}

return ns, nil
}

func (c *Client) Notifications() (notifications.Notifications, error) {
return c.paginate()
}
63 changes: 25 additions & 38 deletions internal/gh/gh_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,19 @@ func mockSubjectUrl(id int) string {
return "https://subject.url/" + strconv.Itoa(id)
}

func mockNotification(id int) *notifications.Notification {
return &notifications.Notification{
Id: strconv.Itoa(id),
Subject: notifications.Subject{
URL: mockSubjectUrl(id),
},
}
}

func mockNotifications(ids []int) []*notifications.Notification {
n := []*notifications.Notification{}
for _, id := range ids {
n = append(n, &notifications.Notification{
Id: strconv.Itoa(id),
Subject: notifications.Subject{
URL: mockSubjectUrl(id),
},
})
n = append(n, mockNotification(id))
}
return n
}
Expand Down Expand Up @@ -467,53 +471,36 @@ func TestPaginate(t *testing.T) {

func TestNotifications(t *testing.T) {
tests := []struct {
name string
calls []mock.Call
notifications []*notifications.Notification
error error
name string
calls mock.Call
notification *notifications.Notification
error error
}{

{
name: "no notification",
},
{
name: "one notification",
calls: []mock.Call{
{Endpoint: mockSubjectUrl(0)},
},
notifications: mockNotifications([]int{0}),
name: "one notification",
calls: mock.Call{Endpoint: mockSubjectUrl(0)},
notification: mockNotification(0),
},
{
name: "multiple notifications",
calls: []mock.Call{
{Endpoint: mockSubjectUrl(0)},
{Endpoint: mockSubjectUrl(1)},
{Endpoint: mockSubjectUrl(2)},
},
notifications: mockNotifications([]int{0, 1, 2}),
},
{
name: "fail to enrich",
calls: []mock.Call{
{Endpoint: mockSubjectUrl(0)},
{Error: sampleError},
},
notifications: mockNotifications([]int{0, 1}),
error: sampleError,
name: "fail to enrich",
calls: mock.Call{Error: sampleError},
notification: mockNotification(0),
error: sampleError,
},
}

for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
client := mockClient(test.calls)
client := mockClient([]mock.Call{test.calls})

notifications, err := client.Enrich(test.notifications)
err := client.Enrich(test.notification)

if test.error == nil {
if !notificationsEqual(notifications, test.notifications) {
t.Errorf("want %#v, got %#v", test.notifications, notifications)
}
} else {
// TODO: make this test check for the author/subject
if test.error != nil {
if !errors.Is(err, test.error) {
t.Errorf("want %#v, got %#v", test.error, err)
}
Expand Down
34 changes: 23 additions & 11 deletions internal/manager/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@ type Manager struct {
config *config.Data
client *gh.Client
Actors actors.ActorsMap
refresh RefreshStrategy

Refresh RefreshStrategy
Force ForceStrategy
}

func New(config *config.Data) *Manager {
Expand All @@ -38,12 +40,6 @@ func (m *Manager) WithCaller(caller api.Caller) *Manager {
return m
}

func (m *Manager) WithRefresh(refresh RefreshStrategy) *Manager {
m.refresh = refresh

return m
}

func (m *Manager) Load() error {
m.Notifications = notifications.Notifications{}

Expand All @@ -64,12 +60,12 @@ func (m *Manager) Load() error {
}

func (m *Manager) shouldRefresh(expired bool) bool {
if !expired && m.refresh == ForceRefresh {
if !expired && m.Refresh == ForceRefresh {
slog.Info("forcing a refresh")
return true
}

if expired && m.refresh == PreventRefresh {
if expired && m.Refresh == PreventRefresh {
slog.Info("preventing a refresh")
return false
}
Expand Down Expand Up @@ -98,7 +94,7 @@ func (m *Manager) refreshNotifications() error {

m.Notifications = m.Notifications.Uniq()

m.Notifications, err = m.client.Enrich(m.Notifications)
m.Notifications, err = m.Enrich(m.Notifications)

return err
}
Expand All @@ -107,6 +103,22 @@ func (m *Manager) Save() error {
return m.cache.Write(m.Notifications.Compact())
}

func (m *Manager) Enrich(ns notifications.Notifications) (notifications.Notifications, error) {
for i, n := range ns {
if n.Meta.Done && !m.Force.Has(ForceEnrich) {
continue
}

if err := m.client.Enrich(n); err != nil {
return nil, err
}

ns[i] = n
}

return ns, nil
}

func (m *Manager) loadCache() (notifications.Notifications, bool, error) {
expired, err := m.cache.Expired()
if err != nil {
Expand Down Expand Up @@ -137,7 +149,7 @@ func (m *Manager) Apply(noop, force bool) error {
slog.Debug("apply rule", "name", rule.Name, "count", len(selectedIds))

for _, notification := range m.Notifications.FilterFromIds(selectedIds) {
if notification.Meta.Done && !force {
if notification.Meta.Done && !m.Force.Has(ForceApply) {
slog.Debug("skipping done notification", "id", notification.Id)
continue
}
Expand Down
47 changes: 0 additions & 47 deletions internal/manager/refreshStrategy.go

This file was deleted.

Loading

0 comments on commit 526ced0

Please sign in to comment.