Files
upstream-corteza/server/system/automation/reminders_handler.go
upstream-mirror 7e385fc126
Some checks failed
SonarQube / SonarQube (push) Failing after 5m28s
E2e test on main branch push / server and client test (map[name:admin port:8080]) (push) Failing after 3m33s
Server and lib tests / Library test (js) (push) Failing after 1m36s
Server and lib tests / Library test (vue) (push) Successful in 2m24s
Server and lib tests / Web client test (admin) (push) Successful in 2m52s
Server and lib tests / Web client test (compose) (push) Successful in 3m23s
Server and lib tests / Web client test (discovery) (push) Successful in 2m49s
Server and lib tests / Web client test (one) (push) Successful in 2m52s
Server and lib tests / Web client test (privacy) (push) Successful in 2m44s
Server and lib tests / Web client test (reporter) (push) Successful in 2m56s
Server and lib tests / Web client test (workflow) (push) Successful in 3m0s
Server and lib tests / Server tests (push) Failing after 4m55s
E2e test on main branch push / notify-failure (push) Failing after 9s
Server and lib tests / Send matrix testing notification (push) Successful in 2s
Mark stale issues and pull requests / stale (push) Successful in 40s
snapshot of https://github.com/cortezaproject/corteza.git (2024.9.x, 2026-09-18; blobs > 131072B omitted)
2026-09-18 01:22:23 +05:00

289 lines
7.7 KiB
Go

package automation
import (
"context"
"fmt"
"time"
intAuth "github.com/cortezaproject/corteza/server/pkg/auth"
"github.com/cortezaproject/corteza/server/pkg/expr"
"github.com/cortezaproject/corteza/server/pkg/filter"
. "github.com/cortezaproject/corteza/server/pkg/expr"
"github.com/cortezaproject/corteza/server/pkg/wfexec"
"github.com/cortezaproject/corteza/server/system/types"
sqlxtypes "github.com/jmoiron/sqlx/types"
)
type(
reminderService interface {
FindByID(ctx context.Context,ID uint64) (*types.Reminder, error)
Find(ctx context.Context, filter types.ReminderFilter) (types.ReminderSet,types.ReminderFilter,error)
Create(ctx context.Context, reminder *types.Reminder) (*types.Reminder,error)
Update(ctx context.Context, reminder *types.Reminder) (*types.Reminder,error)
Delete(ctx context.Context, ID uint64) error
Dismiss(ctx context.Context, ID uint64) error
Snooze(ctx context.Context, ID uint64,remindAt *time.Time) error
}
remindersHandler struct {
reg remindersHandlerRegistry
rSvc reminderService
}
reminderSetIterator struct {
// Item buffer, current item pointer, and total items traversed
ptr uint
buffer types.ReminderSet
total uint
// When filter limit is set, this constraints it
iterLimit uint
useIterLimit bool
// Item loader for additional chunks
filter types.ReminderFilter
loader func() error
// Total reported by the first page
resTotal uint
}
reminderLookup interface {
GetLookup() (bool, uint64, *types.Reminder)
}
)
func RemindersHandler(reg remindersHandlerRegistry,rSvc reminderService) *remindersHandler {
h := &remindersHandler{
reg : reg,
rSvc: rSvc,
}
h.register()
return h
}
func (h remindersHandler) lookup(ctx context.Context, args *remindersLookupArgs) (results *remindersLookupResults, err error){
results = &remindersLookupResults{}
results.Reminder, err = lookupReminder(ctx, h.rSvc, args)
return
}
func (h remindersHandler) search(ctx context.Context,args *remindersSearchArgs) (results *remindersSearchResults,err error){
results = &remindersSearchResults{}
var (
f=types.ReminderFilter{
Resource: args.Resource,
AssignedTo: args.AssignedTo,
ExcludeDismissed: args.ExcludeDismissed,
ScheduledOnly: args.ScheduledOnly,
}
)
if args.hasSort {
if err = f.Sort.Set(args.Sort); err != nil {
return
}
}
if args.hasPageCursor && args.PageCursor != "" {
f.PageCursor = &filter.PagingCursor{}
if err = f.PageCursor.UnmarshalJSON([]byte(args.PageCursor)); err != nil {
return
}
}
if args.hasLimit {
f.Limit = uint(args.Limit)
}
// Total cannot be fetched together with a page cursor
f.IncTotal = args.IncTotal && f.PageCursor == nil
var auxf types.ReminderFilter
results.Reminders, auxf, err = h.rSvc.Find(ctx, f)
results.Total=uint64(auxf.Total)
return
}
func (h remindersHandler) each(ctx context.Context, args *remindersEachArgs) (out wfexec.IteratorHandler, err error){
var(
i = &reminderSetIterator{}
f=types.ReminderFilter{
Resource: args.Resource,
AssignedTo: args.AssignedTo,
ExcludeDismissed: args.ExcludeDismissed,
ScheduledOnly: args.ScheduledOnly,
}
)
if args.hasSort {
if err = f.Sort.Set(args.Sort); err != nil {
return
}
}
if args.hasPageCursor && args.PageCursor != "" {
f.NextPage = &filter.PagingCursor{}
if err = f.NextPage.UnmarshalJSON([]byte(args.PageCursor)); err != nil {
return
}
}
f.IncTotal = args.IncTotal
if args.hasLimit {
i.useIterLimit = true
i.iterLimit = uint(args.Limit)
f.Limit = uint(args.Limit)
if args.Limit > uint64(wfexec.MaxIteratorBufferSize) {
f.Limit = wfexec.MaxIteratorBufferSize
}
i.iterLimit = uint(args.Limit)
} else {
f.Limit = wfexec.MaxIteratorBufferSize
}
i.filter = f
i.loader = func() (err error) {
if i.filter.PageCursor != nil && i.filter.NextPage == nil {
return
}
i.total += i.ptr
i.ptr = 0
i.filter.PageCursor = i.filter.NextPage
i.filter.NextPage = nil
// Total is fetched with the first page only; a paged query cannot carry it
i.filter.IncTotal = i.filter.IncTotal && i.filter.PageCursor == nil
i.buffer, i.filter, err = h.rSvc.Find(ctx, i.filter)
if i.filter.IncTotal {
i.resTotal = i.filter.Total
}
return
}
return i, i.loader()
}
func (h remindersHandler) create(ctx context.Context, args *remindersCreateArgs) (results *remindersCreateResults, err error) {
results = &remindersCreateResults{}
currentUser := intAuth.GetIdentityFromContext(ctx).Identity()
reminder := &types.Reminder{
Resource:args.Resource,
AssignedTo: args.AssignedTo,
AssignedBy: args.AssignedBy,
RemindAt: args.RemindAt,
Payload: args.Payload,
}
if reminder.AssignedTo == 0 {
reminder.AssignedTo = currentUser
}
if reminder.AssignedBy == 0 {
reminder.AssignedBy = currentUser
}
if len(reminder.Payload) == 0 {
reminder.Payload = sqlxtypes.JSONText(`{"title": "", "note": ""}`)
}
if reminder.RemindAt == nil {
return nil, fmt.Errorf("remindAt is required")
}
results.Reminder, err = h.rSvc.Create(ctx, reminder)
return
}
func (h remindersHandler) update(ctx context.Context, args *remindersUpdateArgs) (results *remindersUpdateResults, err error) {
results = &remindersUpdateResults{}
reminder, err := lookupReminder(ctx, h.rSvc, args)
if err != nil {
return nil, err
}
if args.hasResource {
reminder.Resource = args.Resource
}
if args.hasAssignedTo {
reminder.AssignedTo = args.AssignedTo
}
if args.hasAssignedBy {
reminder.AssignedBy = args.AssignedBy
}
if args.hasRemindAt {
reminder.RemindAt = args.RemindAt
}
if args.hasPayload {
reminder.Payload = args.Payload
}
results.Reminder, err = h.rSvc.Update(ctx, reminder)
return
}
func (h remindersHandler) dismiss(ctx context.Context, args *remindersDismissArgs) error {
if id, err := getReminderID(ctx, h.rSvc, args); err != nil {
return err
} else {
return h.rSvc.Dismiss(ctx, id)
}
}
func (h remindersHandler) snooze(ctx context.Context, args *remindersSnoozeArgs) error {
if id, err := getReminderID(ctx, h.rSvc, args); err != nil {
return err
} else {
return h.rSvc.Snooze(ctx, id, args.RemindAt)
}
}
func (h remindersHandler) delete(ctx context.Context, args *remindersDeleteArgs) error {
if id, err := getReminderID(ctx, h.rSvc, args); err != nil {
return err
} else {
return h.rSvc.Delete(ctx, id)
}
}
func getReminderID(ctx context.Context, svc reminderService, args reminderLookup) (uint64, error) {
_, ID, reminder := args.GetLookup()
switch {
case reminder != nil:
return reminder.ID, nil
case ID > 0:
return ID, nil
}
lookupResult, err := lookupReminder(ctx, svc, args)
if err != nil {
return 0, err
}
return lookupResult.ID, nil
}
func lookupReminder(ctx context.Context, svc reminderService, args reminderLookup) (*types.Reminder, error) {
_, ID, reminder := args.GetLookup()
switch {
case reminder != nil:
return reminder, nil
case ID > 0:
return svc.FindByID(ctx, ID)
}
return nil, fmt.Errorf("empty lookup params")
}
func (i *reminderSetIterator) More(context.Context, *expr.Vars) (bool, error) {
a := wfexec.GenericResourceNextCheck(i.useIterLimit, i.ptr, uint(len(i.buffer)), i.total, i.iterLimit, i.filter.NextPage != nil)
return a, nil
}
func (i *reminderSetIterator) Start(context.Context, *expr.Vars) error {
i.ptr = 0
return nil
}
func (i *reminderSetIterator) Next(context.Context, *expr.Vars) (out *expr.Vars, err error) {
if len(i.buffer)-int(i.ptr) <= 0 {
if err = i.loader(); err != nil {
panic(err)
}
}
out = &expr.Vars{}
reminder := *i.buffer[i.ptr] // Make a copy
reminder.Payload = sqlxtypes.JSONText(string(i.buffer[i.ptr].Payload))
out.Set("reminder", Must(NewReminder(&reminder)))
out.Set("total", Must(NewInteger(i.resTotal)))
i.ptr++
return out, nil
}