mirror of
https://github.com/featurebasedb/featurebase.git
synced 2026-08-28 10:54:59 +00:00
implements an fb_exec_requests system table. The purpose of this table is to allow access to internal state to see what queries are running and have been run.
Co-authored-by: Travis Turner <travis@molecula.com>
(cherry picked from commit 47d8be26f5)
108 lines
2.6 KiB
Go
108 lines
2.6 KiB
Go
package systemlayer
|
|
|
|
import (
|
|
"fmt"
|
|
"sync"
|
|
"time"
|
|
|
|
pilosa "github.com/molecula/featurebase/v3"
|
|
)
|
|
|
|
// ExecutionRequests is an internal struct that keeps a list of sql execution requests
|
|
// this data allows visbility into queries that have been run and are running
|
|
type ExecutionRequests struct {
|
|
sync.RWMutex
|
|
requests map[string]*pilosa.ExecutionRequest
|
|
}
|
|
|
|
// Ensure type implements interface.
|
|
var _ pilosa.ExecutionRequestsAPI = (*ExecutionRequests)(nil)
|
|
|
|
func NewExecutionRequestsAPI() *ExecutionRequests {
|
|
return &ExecutionRequests{
|
|
requests: make(map[string]*pilosa.ExecutionRequest),
|
|
}
|
|
}
|
|
|
|
// AddRequest adds a new request to the ExecutionRequests struct
|
|
// TODO(pok) ensure a cap on these so we don't suck up too much memory
|
|
func (e *ExecutionRequests) AddRequest(requestID string, userID string, startTime time.Time, sql string) error {
|
|
e.Lock()
|
|
defer e.Unlock()
|
|
|
|
_, ok := e.requests[requestID]
|
|
if ok {
|
|
return fmt.Errorf("request %s already exists", requestID)
|
|
}
|
|
e.requests[requestID] = &pilosa.ExecutionRequest{
|
|
RequestID: requestID,
|
|
UserID: userID,
|
|
StartTime: startTime,
|
|
Status: "running",
|
|
SQL: sql,
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// UpdateRequest updates the values for a request in the ExecutionRequests struct
|
|
func (e *ExecutionRequests) UpdateRequest(requestID string,
|
|
endTime time.Time,
|
|
status string,
|
|
waitType string,
|
|
waitTime time.Duration,
|
|
waitResource string,
|
|
cpuTime time.Duration,
|
|
reads int64,
|
|
writes int64,
|
|
logicalReads int64,
|
|
rowCount int64,
|
|
plan string) error {
|
|
|
|
e.Lock()
|
|
defer e.Unlock()
|
|
|
|
request, ok := e.requests[requestID]
|
|
if !ok {
|
|
return fmt.Errorf("request %s not found", requestID)
|
|
}
|
|
request.EndTime = endTime
|
|
request.Status = status
|
|
request.WaitType = waitType
|
|
request.WaitTime += waitTime
|
|
request.WaitResource = waitResource
|
|
request.CPUTime += cpuTime
|
|
request.Reads += reads
|
|
request.Writes += writes
|
|
request.LogicalReads += logicalReads
|
|
request.RowCount += rowCount
|
|
request.Plan = plan
|
|
|
|
return nil
|
|
}
|
|
|
|
// ListRequests returns the content of the ExecutionRequests struct as copies
|
|
func (e *ExecutionRequests) ListRequests() ([]pilosa.ExecutionRequest, error) {
|
|
e.RLock()
|
|
defer e.RUnlock()
|
|
|
|
result := make([]pilosa.ExecutionRequest, len(e.requests))
|
|
|
|
idx := 0
|
|
for _, er := range e.requests {
|
|
result[idx] = er.Copy()
|
|
idx++
|
|
}
|
|
return result, nil
|
|
}
|
|
|
|
func (e *ExecutionRequests) GetRequest(requestID string) (pilosa.ExecutionRequest, error) {
|
|
e.RLock()
|
|
defer e.RUnlock()
|
|
|
|
er, ok := e.requests[requestID]
|
|
if !ok {
|
|
return pilosa.ExecutionRequest{}, fmt.Errorf("request %s not found", requestID)
|
|
}
|
|
|
|
return er.Copy(), nil
|
|
}
|