Rebuild SCUM plugin-owned data flow
This commit is contained in:
@@ -0,0 +1,92 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"browser.local/platform/domain"
|
||||
)
|
||||
|
||||
func (svc *CoreService) scheduleDuePluginQueries(runEndpointID string, capabilities []string, stamp time.Time) error {
|
||||
if !containsString(capabilities, domain.JobCapabilityRemoteRunDBSQLiteQuery) {
|
||||
return nil
|
||||
}
|
||||
instances, err := svc.store.ServerInstances().List(domain.ServerInstanceFilter{RunEndpointID: runEndpointID})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
jobs, err := svc.store.Jobs().List(domain.JobFilter{RunEndpointID: runEndpointID})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, instance := range instances {
|
||||
if instance.State == domain.ServerInstanceStateDeleted {
|
||||
continue
|
||||
}
|
||||
plugin, getErr := svc.store.GamePlugins().Get(instance.PluginID)
|
||||
if getErr != nil {
|
||||
return getErr
|
||||
}
|
||||
for _, template := range plugin.GameClientBridge.QueryTemplates {
|
||||
if template.PollIntervalSeconds <= 0 || template.RowTarget == nil || strings.TrimSpace(template.SQLRef) == "" {
|
||||
continue
|
||||
}
|
||||
if !pluginQueryTemplateDue(jobs, instance.ID, template.Key, time.Duration(template.PollIntervalSeconds)*time.Second, stamp) {
|
||||
continue
|
||||
}
|
||||
bucket := stamp.Unix() / int64(template.PollIntervalSeconds)
|
||||
idempotencyKey := fmt.Sprintf("plugin-query:%s:%s:%d", instance.ID, template.Key, bucket)
|
||||
job := domain.Job{
|
||||
ID: jobIDFromParts("job-plugin-query", instance.ID, idempotencyKey),
|
||||
ServerInstanceID: instance.ID,
|
||||
RunEndpointID: runEndpointID,
|
||||
Capability: domain.JobCapabilityRemoteRunDBSQLiteQuery,
|
||||
TargetKey: template.TargetKey,
|
||||
InputRef: "input://plugin-query/" + template.Key,
|
||||
IdempotencyKey: idempotencyKey,
|
||||
Progress: domain.JobProgress{Percent: 0, Message: "declared automatic plugin query queued"},
|
||||
RetryPolicy: domain.JobRetryPolicy{MaxAttempts: 1, InitialBackoffSeconds: 1, MaxBackoffSeconds: 1},
|
||||
ExecutionInput: domain.JobExecutionInput{
|
||||
WorkspaceScope: svc.runtimeProfileScope(instance.ID),
|
||||
RemoteAdapterKey: template.TransportKey,
|
||||
RemoteAdapterKind: string(domain.RemoteAdapterDatabase),
|
||||
TimeoutSeconds: template.TimeoutSeconds,
|
||||
Inputs: map[string]string{
|
||||
"templateKey": template.Key,
|
||||
"sqlRef": template.SQLRef,
|
||||
"maxRows": strconv.Itoa(template.MaxRows),
|
||||
"limit": strconv.Itoa(template.MaxRows),
|
||||
},
|
||||
},
|
||||
}
|
||||
created, createErr := svc.CreateJob(job)
|
||||
if createErr != nil {
|
||||
return createErr
|
||||
}
|
||||
jobs = append(jobs, created)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func pluginQueryTemplateDue(jobs []domain.Job, serverInstanceID, templateKey string, interval time.Duration, stamp time.Time) bool {
|
||||
var latest time.Time
|
||||
for _, job := range jobs {
|
||||
if job.ServerInstanceID != serverInstanceID || job.Capability != domain.JobCapabilityRemoteRunDBSQLiteQuery || job.ExecutionInput.Inputs["templateKey"] != templateKey {
|
||||
continue
|
||||
}
|
||||
if !isTerminalJobState(job.State) {
|
||||
return false
|
||||
}
|
||||
attemptedAt := job.TerminalAt
|
||||
if attemptedAt.IsZero() {
|
||||
attemptedAt = job.UpdatedAt
|
||||
}
|
||||
if attemptedAt.After(latest) {
|
||||
latest = attemptedAt
|
||||
}
|
||||
}
|
||||
return latest.IsZero() || !stamp.Before(latest.Add(interval))
|
||||
}
|
||||
Reference in New Issue
Block a user