summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--golib/eows/eows-out.go61
-rw-r--r--golib/eows/eows.go10
2 files changed, 53 insertions, 18 deletions
diff --git a/golib/eows/eows-out.go b/golib/eows/eows-out.go
index 6f6706c..b70e70c 100644
--- a/golib/eows/eows-out.go
+++ b/golib/eows/eows-out.go
@@ -4,16 +4,52 @@ import (
"bufio"
"io"
"strings"
+ "time"
)
-// scanBlocks - gain character by character (or as soon as one or more characters are available)
-func scanBlocks(data []byte, atEOF bool) (advance int, token []byte, err error) {
+// scanChars - gain character by character (or as soon as one or more characters are available)
+func scanChars(data []byte, atEOF bool) (advance int, token []byte, err error) {
if atEOF && len(data) == 0 {
return 0, nil, nil
}
return len(data), data, nil
}
+// _pumper is in charge to collect
+func (e *ExecOverWS) _pumper(sc *bufio.Scanner, fctOut func(s string)) {
+
+ // Select split function (default sc.ScanLines)
+ if e.OutSplit == SplitChar || e.OutSplit == SplitLineTime || e.OutSplit == SplitTime {
+ sc.Split(scanChars)
+ }
+
+ // Scan method according to split type
+ if e.OutSplit == SplitLineTime || e.OutSplit == SplitTime {
+ t0 := time.Now()
+ buf := ""
+ for sc.Scan() {
+ buf += sc.Text()
+ if time.Since(t0).Nanoseconds() > e.LineTimeSpan ||
+ (e.OutSplit == SplitLineTime && strings.Contains(buf, "\n")) {
+ fctOut(buf)
+ buf = ""
+ t0 = time.Now()
+ }
+ }
+ // Send remaining characters
+ if len(buf) > 0 {
+ e.OutputCB(e, "", buf)
+ }
+
+ } else {
+
+ for sc.Scan() {
+ e.OutputCB(e, sc.Text(), "")
+ }
+ }
+
+}
+
// cmdPumpStdout is in charge to forward stdout in websocket
func (e *ExecOverWS) cmdPumpStdout(r io.Reader, done chan struct{}) {
@@ -22,14 +58,10 @@ func (e *ExecOverWS) cmdPumpStdout(r io.Reader, done chan struct{}) {
sc := bufio.NewScanner(r)
- // else use default sc.ScanLines
- if e.OutSplit == SplitChar {
- sc.Split(scanBlocks)
- }
+ e._pumper(sc, func(bufOut string) {
+ e.OutputCB(e, bufOut, "")
+ })
- for sc.Scan() {
- e.OutputCB(e, sc.Text(), "")
- }
if sc.Err() != nil && !strings.Contains(sc.Err().Error(), "file already closed") {
e.logError("stdout scan: %v", sc.Err())
}
@@ -42,16 +74,13 @@ func (e *ExecOverWS) cmdPumpStderr(r io.Reader) {
defer func() {
}()
+
sc := bufio.NewScanner(r)
- // else use default sc.ScanLines
- if e.OutSplit == SplitChar {
- sc.Split(scanBlocks)
- }
+ e._pumper(sc, func(bufErr string) {
+ e.OutputCB(e, "", bufErr)
+ })
- for sc.Scan() {
- e.OutputCB(e, "", sc.Text())
- }
if sc.Err() != nil && !strings.Contains(sc.Err().Error(), "file already closed") {
e.logError("stderr scan: %v", sc.Err())
}
diff --git a/golib/eows/eows.go b/golib/eows/eows.go
index a5767ed..192be3d 100644
--- a/golib/eows/eows.go
+++ b/golib/eows/eows.go
@@ -28,6 +28,10 @@ const (
SplitLine SplitType = iota
// SplitChar Split character by character
SplitChar
+ // SplitLineTime Split by line or until a timeout has passed
+ SplitLineTime
+ // SplitTime Split until a timeout has passed
+ SplitTime
)
// Inspired by :
@@ -51,6 +55,7 @@ type ExecOverWS struct {
ExitCB EmitExitCB // exit proc callback
UserData *map[string]interface{} // user data passed to callbacks
OutSplit SplitType // split method to tokenize stdout/stderr
+ LineTimeSpan int64 // time span (only used with SplitTime or SplitLineTime)
// Private fields
proc *os.Process
@@ -67,8 +72,9 @@ func New(cmd string, args []string, so *socketio.Socket, soID, cmdID string) *Ex
SocketIO: so,
Sid: soID,
CmdID: cmdID,
- CmdExecTimeout: -1, // default no timeout
- OutSplit: SplitChar, // default split by character
+ CmdExecTimeout: -1, // default no timeout
+ OutSplit: SplitLineTime, // default split by line with time
+ LineTimeSpan: 500 * time.Millisecond.Nanoseconds(),
}
cmdIDMap[cmdID] = e