code to stream stdout to the browser

This commit is contained in:
Brad Rydzewski 2014-07-11 19:10:18 -07:00
parent 6375eaa552
commit d000ca2918
9 changed files with 37 additions and 52 deletions

View file

@ -31,6 +31,8 @@
<script src="//cdnjs.cloudflare.com/ajax/libs/moment.js/2.6.0/moment.min.js"></script>
<!-- main javascript application -->
<script src="/scripts/line_formatter.js"></script>
<script src="/scripts/commit_updates.js"></script>
<script src="/scripts/app.js"></script>
<script src="/scripts/controllers/conf.js"></script>
<script src="/scripts/controllers/home.js"></script>

View file

@ -213,11 +213,11 @@ app.controller("CommitController", function($scope, $http, $routeParams, stdout,
var name = $routeParams.name;
var branch = $routeParams.branch;
var commit = $routeParams.commit;
$scope.console='';
feed.subscribe(function(item) {
// if the
if (item.commit.sha == commit
&& item.commit.branch == branch) {
if (item.commit.sha == commit &&
item.commit.branch == branch) {
$scope.commit = item.commit;
$scope.$apply();
} else {
@ -247,15 +247,20 @@ app.controller("CommitController", function($scope, $http, $routeParams, stdout,
if (data.status!='Started' && data.status!='Pending') {
$http({method: 'GET', url: '/v1/repos/'+remote+'/'+owner+"/"+name+"/branches/"+branch+"/commits/"+commit+"/console"}).
success(function(data, status, headers, config) {
$scope.console = data;
var lineFormatter = new Drone.LineFormatter();
var el = document.querySelector('#output');
angular.element(el).append(lineFormatter.format(data));
}).
error(function(data, status, headers, config) {
console.log(data);
});
return;
}
var lineFormatter = new Drone.LineFormatter();
var el = document.querySelector('#output');
stdout.subscribe(data.id, function(out){
console.log(out);
angular.element(el).append(lineFormatter.format(out));
});
}).
error(function(data, status, headers, config) {

View file

@ -3,49 +3,29 @@
if(typeof(Drone) === 'undefined') { Drone = {}; }
(function () {
Drone.CommitUpdates = function(socket) {
if(typeof(socket) === "string") {
var url = [(window.location.protocol == 'https:' ? 'wss' : 'ws'),
'://',
window.location.host,
socket].join('')
this.socket = new WebSocket(url);
} else {
this.socket = socket;
}
Drone.Console = function() {
this.lineFormatter = new Drone.LineFormatter();
this.attach();
}
Drone.CommitUpdates.prototype = {
Drone.Console.prototype = {
lineBuffer: "",
autoFollow: false,
startOutput: function(el) {
start: function(el) {
if(typeof(el) === 'string') {
this.el = document.getElementById(el);
} else {
this.el = el;
}
if(!this.reqId) {
this.updateScreen();
}
this.update();
},
stopOutput: function() {
stop: function() {
this.stoppingRefresh = true;
},
attach: function() {
this.socket.onopen = this.onOpen;
this.socket.onerror = this.onError;
this.socket.onmessage = this.onMessage.bind(this);
this.socket.onclose = this.onClose;
},
updateScreen: function() {
update: function() {
if(this.lineBuffer.length > 0) {
this.el.innerHTML += this.lineBuffer;
this.lineBuffer = '';
@ -62,21 +42,8 @@ if(typeof(Drone) === 'undefined') { Drone = {}; }
}
},
onOpen: function() {
console.log('output websocket open');
},
onError: function(e) {
console.log('websocket error: ' + e);
},
onMessage: function(e) {
write: function(e) {
this.lineBuffer += this.lineFormatter.format(e.data);
},
onClose: function(e) {
console.log('output websocket closed: ' + JSON.stringify(e));
window.location.reload();
}
};

View file

@ -24,6 +24,7 @@ angular.module('app').service('stdout', ['$window', function($window) {
this.unsubscribe = function() {
callback = undefined;
if (websocket != undefined) {
console.log('unsubscribing websocket at '+websocket.url);
websocket.close();
}
};

View file

@ -29,6 +29,6 @@
<a href="#">{{ commit.sha | shortHash}}</a>
</nav>
<pre>{{ console }}</pre>
<pre id="output"></pre>
</div>
</div>

View file

@ -46,8 +46,6 @@ func (h *HookHandler) PostHook(w http.ResponseWriter, r *http.Request) error {
return nil
}
//fmt.Printf("%#v", hook)
// fetch the repository from the database
repo, err := h.repos.FindName(remote.GetHost(), hook.Owner, hook.Repo)
if err != nil {

View file

@ -1,6 +1,7 @@
package handler
import (
"log"
"net/http"
"strconv"
"time"
@ -157,16 +158,19 @@ func (h *WsHandler) WsConsole(w http.ResponseWriter, r *http.Request) error {
ws.SetWriteDeadline(time.Now().Add(writeWait))
err := ws.WriteMessage(websocket.TextMessage, data)
if err != nil {
log.Println("websocket for commit %d closed. Err: %s", commitID, err)
ws.Close()
return
}
case <-sub.CloseNotify():
log.Println("websocket for commit %d closed by client", commitID)
ws.Close()
return
case <-ticker.C:
ws.SetWriteDeadline(time.Now().Add(writeWait))
err := ws.WriteMessage(websocket.PingMessage, []byte{})
if err != nil {
log.Println("websocket for commit %d closed. Err: %s", commitID, err)
ws.Close()
return
}

View file

@ -1,6 +1,7 @@
package pubsub
import (
"log"
"time"
)
@ -47,7 +48,9 @@ func (c *Channel) start() {
// if somehow we encounter a nil pointer or some
// other unexpected behavior.
defer func() {
recover()
if r := recover(); r != nil {
log.Println("recoved from panic", r)
}
}()
// timeout the channel after N duration
@ -63,6 +66,7 @@ func (c *Channel) start() {
case sub := <-c.unsubscribe:
delete(c.subscriptions, sub)
close(sub.send)
log.Println("usubscribed to subscription")
case sub := <-c.subscribe:
c.subscriptions[sub] = true
@ -89,15 +93,18 @@ func (c *Channel) start() {
select {
case sub.send <- msg:
// do nothing
default:
sub.Close()
//default:
// log.Println("subscription closed in inner select")
// sub.Close()
}
}
case <-timeout:
log.Println("subscription's timedout channel received message")
c.Close()
case <-c.closed:
log.Println("subscription's close channel received message")
c.stop()
return
}
@ -111,6 +118,7 @@ func replay(s *Subscription, history []interface{}) {
}
func (c *Channel) stop() {
log.Println("subscription stopped")
for sub := range c.subscriptions {
sub.Close()
}

View file

@ -21,6 +21,6 @@ var DefaultOpts = &Opts{
}
var ConsoleOpts = &Opts{
Timeout: time.Minute * 60,
Timeout: time.Minute * 120,
Record: true,
}