parent
62e7037f20
commit
73dbfc9461
3 changed files with 26 additions and 37 deletions
|
|
@ -26,9 +26,9 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type worker struct {
|
type worker struct {
|
||||||
ts graph.TripleStore
|
ts graph.TripleStore
|
||||||
env *otto.Otto
|
env *otto.Otto
|
||||||
envLock sync.Mutex
|
sync.Mutex
|
||||||
|
|
||||||
results chan interface{}
|
results chan interface{}
|
||||||
shape map[string]interface{}
|
shape map[string]interface{}
|
||||||
|
|
@ -36,7 +36,7 @@ type worker struct {
|
||||||
count int
|
count int
|
||||||
limit int
|
limit int
|
||||||
|
|
||||||
kill chan struct{}
|
kill <-chan struct{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func newWorker(ts graph.TripleStore) *worker {
|
func newWorker(ts graph.TripleStore) *worker {
|
||||||
|
|
|
||||||
|
|
@ -251,11 +251,8 @@ func (wk *worker) send(r *Result) bool {
|
||||||
if wk.limit >= 0 && wk.limit == wk.count {
|
if wk.limit >= 0 && wk.limit == wk.count {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
wk.envLock.Lock()
|
|
||||||
kill := wk.kill
|
|
||||||
wk.envLock.Unlock()
|
|
||||||
select {
|
select {
|
||||||
case <-kill:
|
case <-wk.kill:
|
||||||
return false
|
return false
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -33,10 +33,12 @@ type Session struct {
|
||||||
ts graph.TripleStore
|
ts graph.TripleStore
|
||||||
|
|
||||||
wk *worker
|
wk *worker
|
||||||
timeout time.Duration
|
|
||||||
script *otto.Script
|
script *otto.Script
|
||||||
persist *otto.Otto
|
persist *otto.Otto
|
||||||
|
|
||||||
|
timeout time.Duration
|
||||||
|
kill chan struct{}
|
||||||
|
|
||||||
debug bool
|
debug bool
|
||||||
dataOutput []interface{}
|
dataOutput []interface{}
|
||||||
|
|
||||||
|
|
@ -84,10 +86,12 @@ func (s *Session) InputParses(input string) (query.ParseResult, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Session) runUnsafe(input interface{}) (otto.Value, error) {
|
func (s *Session) runUnsafe(input interface{}) (otto.Value, error) {
|
||||||
|
wk := s.wk
|
||||||
defer func() {
|
defer func() {
|
||||||
if r := recover(); r != nil {
|
if r := recover(); r != nil {
|
||||||
if r == ErrKillTimeout {
|
if r == ErrKillTimeout {
|
||||||
s.err = ErrKillTimeout
|
s.err = ErrKillTimeout
|
||||||
|
wk.env = s.persist
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
panic(r)
|
panic(r)
|
||||||
|
|
@ -95,43 +99,34 @@ func (s *Session) runUnsafe(input interface{}) (otto.Value, error) {
|
||||||
}()
|
}()
|
||||||
|
|
||||||
// Use buffered chan to prevent blocking.
|
// Use buffered chan to prevent blocking.
|
||||||
s.wk.env.Interrupt = make(chan func(), 1)
|
wk.env.Interrupt = make(chan func(), 1)
|
||||||
|
s.kill = make(chan struct{})
|
||||||
|
wk.kill = s.kill
|
||||||
|
|
||||||
ready := make(chan struct{})
|
|
||||||
done := make(chan struct{})
|
done := make(chan struct{})
|
||||||
|
defer close(done)
|
||||||
if s.timeout >= 0 {
|
if s.timeout >= 0 {
|
||||||
go func() {
|
go func() {
|
||||||
time.Sleep(s.timeout)
|
time.Sleep(s.timeout)
|
||||||
<-ready
|
|
||||||
select {
|
select {
|
||||||
case <-done:
|
case <-done:
|
||||||
return
|
|
||||||
default:
|
default:
|
||||||
close(s.wk.kill)
|
close(s.kill)
|
||||||
s.wk.envLock.Lock()
|
wk.Lock()
|
||||||
defer s.wk.envLock.Unlock()
|
if wk.env != nil {
|
||||||
s.wk.kill = nil
|
wk.env.Interrupt <- func() {
|
||||||
if s.wk.env != nil {
|
|
||||||
s.wk.env.Interrupt <- func() {
|
|
||||||
panic(ErrKillTimeout)
|
panic(ErrKillTimeout)
|
||||||
}
|
}
|
||||||
s.wk.env = s.persist
|
|
||||||
}
|
}
|
||||||
return
|
wk.Unlock()
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
s.wk.envLock.Lock()
|
wk.Lock()
|
||||||
env := s.wk.env
|
env := wk.env
|
||||||
if s.wk.kill == nil {
|
wk.Unlock()
|
||||||
s.wk.kill = make(chan struct{})
|
return env.Run(input)
|
||||||
}
|
|
||||||
s.wk.envLock.Unlock()
|
|
||||||
close(ready)
|
|
||||||
out, err := env.Run(input)
|
|
||||||
close(done)
|
|
||||||
return out, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Session) ExecInput(input string, out chan interface{}, _ int) {
|
func (s *Session) ExecInput(input string, out chan interface{}, _ int) {
|
||||||
|
|
@ -152,9 +147,9 @@ func (s *Session) ExecInput(input string, out chan interface{}, _ int) {
|
||||||
}
|
}
|
||||||
s.wk.results = nil
|
s.wk.results = nil
|
||||||
s.script = nil
|
s.script = nil
|
||||||
s.wk.envLock.Lock()
|
s.wk.Lock()
|
||||||
s.wk.env = s.persist
|
s.wk.env = s.persist
|
||||||
s.wk.envLock.Unlock()
|
s.wk.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Session) ToText(result interface{}) string {
|
func (s *Session) ToText(result interface{}) string {
|
||||||
|
|
@ -242,11 +237,8 @@ func (s *Session) GetJson() ([]interface{}, error) {
|
||||||
if s.err != nil {
|
if s.err != nil {
|
||||||
return nil, s.err
|
return nil, s.err
|
||||||
}
|
}
|
||||||
s.wk.envLock.Lock()
|
|
||||||
kill := s.wk.kill
|
|
||||||
s.wk.envLock.Unlock()
|
|
||||||
select {
|
select {
|
||||||
case <-kill:
|
case <-s.kill:
|
||||||
return nil, ErrKillTimeout
|
return nil, ErrKillTimeout
|
||||||
default:
|
default:
|
||||||
return s.dataOutput, nil
|
return s.dataOutput, nil
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue