Files
upstream-corteza/server/compose/service/export_session.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

144 lines
3.3 KiB
Go

package service
import (
"context"
"fmt"
"sync"
"time"
"github.com/cortezaproject/corteza/server/pkg/auth"
)
const (
exportSessionTTL = time.Hour
)
type (
RecordExportSession struct {
SessionID uint64 `json:"sessionID,string"`
UserID uint64 `json:"userID,string"`
NamespaceID uint64 `json:"namespaceID,string"`
ModuleID uint64 `json:"moduleID,string"`
Filename string `json:"filename"`
Ext string `json:"ext"`
Filter string `json:"filter"`
Fields []string `json:"fields"`
Timezone string `json:"timezone"`
MultiValueDelimiter string `json:"multiValueDelimiter"`
WrapMultiValue string `json:"wrapMultiValue"`
ResolveRefs bool `json:"resolveRefs"`
IncludeRefID bool `json:"includeRefID"`
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"updatedAt"`
}
exportSessionSet []*RecordExportSession
exportSession struct {
l sync.Mutex
sessions exportSessionSet
}
ExportSessionService interface {
Create(ctx context.Context, s *RecordExportSession) (*RecordExportSession, error)
FindByID(ctx context.Context, sessionID uint64) (*RecordExportSession, error)
DeleteByID(ctx context.Context, sessionID uint64) error
}
)
func ExportSession() *exportSession {
svc := &exportSession{
sessions: exportSessionSet{},
}
go svc.cleanupLoop(context.Background())
return svc
}
func (svc *exportSession) indexOf(userID, sessionID uint64) int {
for i, r := range svc.sessions {
if r.SessionID == sessionID && r.UserID == userID {
return i
}
}
return -1
}
func (svc *exportSession) Create(ctx context.Context, s *RecordExportSession) (*RecordExportSession, error) {
svc.l.Lock()
defer svc.l.Unlock()
s.SessionID = nextID()
s.UserID = auth.GetIdentityFromContext(ctx).Identity()
s.CreatedAt = time.Now()
s.UpdatedAt = s.CreatedAt
svc.sessions = append(svc.sessions, s)
return s, nil
}
func (svc *exportSession) FindByID(ctx context.Context, sessionID uint64) (*RecordExportSession, error) {
svc.l.Lock()
defer svc.l.Unlock()
userID := auth.GetIdentityFromContext(ctx).Identity()
i := svc.indexOf(userID, sessionID)
if i < 0 {
return nil, fmt.Errorf("compose.service.RecordExportSessionNotFound")
}
s := svc.sessions[i]
if time.Since(s.UpdatedAt) > exportSessionTTL {
svc.sessions = removeExportSession(svc.sessions, i)
return nil, fmt.Errorf("compose.service.RecordExportSessionNotFound")
}
return s, nil
}
func (svc *exportSession) DeleteByID(ctx context.Context, sessionID uint64) error {
svc.l.Lock()
defer svc.l.Unlock()
userID := auth.GetIdentityFromContext(ctx).Identity()
i := svc.indexOf(userID, sessionID)
if i >= 0 {
svc.sessions = removeExportSession(svc.sessions, i)
}
return nil
}
func removeExportSession(s exportSessionSet, i int) exportSessionSet {
s[len(s)-1], s[i] = s[i], s[len(s)-1]
return s[:len(s)-1]
}
func (svc *exportSession) cleanupLoop(ctx context.Context) {
t := time.NewTicker(10 * time.Minute)
defer t.Stop()
for {
select {
case <-ctx.Done():
return
case <-t.C:
svc.clean()
}
}
}
func (svc *exportSession) clean() {
svc.l.Lock()
defer svc.l.Unlock()
for i := len(svc.sessions) - 1; i >= 0; i-- {
if time.Since(svc.sessions[i].UpdatedAt) > exportSessionTTL {
svc.sessions = removeExportSession(svc.sessions, i)
}
}
}