fixing tests and some subtle issues with saving contents #16
@@ -35,33 +35,27 @@ func (ch *CaddyHugo) LTime() uint64 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (ch *CaddyHugo) ShouldApply(ltime uint64) bool {
|
func (ch *CaddyHugo) ShouldApply(ltime uint64) bool {
|
||||||
lowest := ch.LowestPendingConfirmation()
|
|
||||||
for _, c := range ch.Confirming() {
|
|
||||||
if lowest == 0 || c < lowest {
|
|
||||||
lowest = c
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ltime < lowest {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
ch.mtx.Lock()
|
ch.mtx.Lock()
|
||||||
defer ch.mtx.Unlock()
|
defer ch.mtx.Unlock()
|
||||||
|
|
||||||
if _, ok := ch.confirmingToClient[ltime]; ok {
|
if _, ok := ch.confirmingToClient[ltime]; ok {
|
||||||
|
fmt.Println("rejecting ltime", ltime, "because was already processed")
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ConfirmLTime marks an ltime as something that should be confirmed with clients
|
||||||
func (ch *CaddyHugo) ConfirmLTime(ltime uint64) {
|
func (ch *CaddyHugo) ConfirmLTime(ltime uint64) {
|
||||||
ch.mtx.Lock()
|
ch.mtx.Lock()
|
||||||
defer ch.mtx.Unlock()
|
defer ch.mtx.Unlock()
|
||||||
ch.confirmingToClient[ltime] = struct{}{}
|
ch.confirmingToClient[ltime] = struct{}{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Confirming returns the current list of LTimes that need to be confirmed
|
||||||
|
// to clients
|
||||||
func (ch *CaddyHugo) Confirming() []uint64 {
|
func (ch *CaddyHugo) Confirming() []uint64 {
|
||||||
var times []uint64
|
var times []uint64
|
||||||
|
|
||||||
@@ -74,6 +68,8 @@ func (ch *CaddyHugo) Confirming() []uint64 {
|
|||||||
return times
|
return times
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// LowestPendingConfirmation identifies the lowest LTime that needs to be
|
||||||
|
// confirmed to clients
|
||||||
func (ch *CaddyHugo) LowestPendingConfirmation() uint64 {
|
func (ch *CaddyHugo) LowestPendingConfirmation() uint64 {
|
||||||
var lowest uint64
|
var lowest uint64
|
||||||
for _, c := range ch.Confirming() {
|
for _, c := range ch.Confirming() {
|
||||||
@@ -128,7 +124,7 @@ func (ch *CaddyHugo) Message(deltas ...acedoc.Delta) Message {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (ch *CaddyHugo) handleDeltaConn(conn DeltaConn, doc *editSession) (int, error) {
|
func (ch *CaddyHugo) handleDeltaConn(conn DeltaConn, doc *editSession) (int, error) {
|
||||||
const idlePing = 15 * time.Second
|
const idlePing = 1 * time.Second
|
||||||
const idlePingShort = 1 * time.Millisecond
|
const idlePingShort = 1 * time.Millisecond
|
||||||
|
|
||||||
errCh := make(chan error)
|
errCh := make(chan error)
|
||||||
@@ -157,6 +153,7 @@ func (ch *CaddyHugo) handleDeltaConn(conn DeltaConn, doc *editSession) (int, err
|
|||||||
client := doc.doc.Client(acedoc.DeltaHandlerFunc(func(ds []acedoc.Delta) error {
|
client := doc.doc.Client(acedoc.DeltaHandlerFunc(func(ds []acedoc.Delta) error {
|
||||||
m := ch.Message(ds...)
|
m := ch.Message(ds...)
|
||||||
wroteMessagesCh <- m
|
wroteMessagesCh <- m
|
||||||
|
fmt.Println("WRITING")
|
||||||
return conn.WriteJSON(m)
|
return conn.WriteJSON(m)
|
||||||
}))
|
}))
|
||||||
|
|
||||||
@@ -181,16 +178,18 @@ func (ch *CaddyHugo) handleDeltaConn(conn DeltaConn, doc *editSession) (int, err
|
|||||||
errCh <- fmt.Errorf("error reading message from client conn: %v", err)
|
errCh <- fmt.Errorf("error reading message from client conn: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
ch.ObserveLTime(message.LTime)
|
if message.LTime != 0 {
|
||||||
|
ch.ObserveLTime(message.LTime)
|
||||||
|
}
|
||||||
|
|
||||||
if len(message.Deltas) == 0 {
|
if len(message.Deltas) == 0 {
|
||||||
time.Sleep(10 * time.Microsecond)
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if !ch.ShouldApply(message.LTime) {
|
if !ch.ShouldApply(message.LTime) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
fmt.Printf("READ %p\n", conn)
|
||||||
|
|
||||||
err = client.PushDeltas(message.Deltas...)
|
err = client.PushDeltas(message.Deltas...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
+11
-8
@@ -100,6 +100,7 @@ type WebsocketTester struct {
|
|||||||
mtx sync.Mutex
|
mtx sync.Mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ReadJSON reads the next pending message from the "client" into v
|
||||||
func (ws *WebsocketTester) ReadJSON(v interface{}) error {
|
func (ws *WebsocketTester) ReadJSON(v interface{}) error {
|
||||||
ws.mtx.Lock()
|
ws.mtx.Lock()
|
||||||
defer ws.mtx.Unlock()
|
defer ws.mtx.Unlock()
|
||||||
@@ -113,6 +114,7 @@ func (ws *WebsocketTester) ReadJSON(v interface{}) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WriteJSON "sends" a message, v, to the "client"
|
||||||
func (ws *WebsocketTester) WriteJSON(v interface{}) error {
|
func (ws *WebsocketTester) WriteJSON(v interface{}) error {
|
||||||
ws.mtx.Lock()
|
ws.mtx.Lock()
|
||||||
defer ws.mtx.Unlock()
|
defer ws.mtx.Unlock()
|
||||||
@@ -122,16 +124,13 @@ func (ws *WebsocketTester) WriteJSON(v interface{}) error {
|
|||||||
panic("wrong type written to WebsocketTester")
|
panic("wrong type written to WebsocketTester")
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(m.Deltas) == 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
ws.wroteMessages = append(ws.wroteMessages, m)
|
ws.wroteMessages = append(ws.wroteMessages, m)
|
||||||
ws.wroteDeltas = append(ws.wroteDeltas, m.Deltas...)
|
ws.wroteDeltas = append(ws.wroteDeltas, m.Deltas...)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ReceiveJSON queues a message to be sent to the client
|
||||||
func (ws *WebsocketTester) ReceiveJSON(v interface{}) error {
|
func (ws *WebsocketTester) ReceiveJSON(v interface{}) error {
|
||||||
ws.mtx.Lock()
|
ws.mtx.Lock()
|
||||||
defer ws.mtx.Unlock()
|
defer ws.mtx.Unlock()
|
||||||
@@ -177,6 +176,7 @@ func TestDeltasSingle(t *testing.T) {
|
|||||||
// so we expect to have written 0 messages
|
// so we expect to have written 0 messages
|
||||||
if len(client.wroteMessages) != 0 {
|
if len(client.wroteMessages) != 0 {
|
||||||
t.Errorf("client wrote %d messages, should have written %d", len(client.wroteMessages), 0)
|
t.Errorf("client wrote %d messages, should have written %d", len(client.wroteMessages), 0)
|
||||||
|
t.Logf("%v", client.wroteMessages)
|
||||||
}
|
}
|
||||||
|
|
||||||
// we received one, so make sure that's counted properly
|
// we received one, so make sure that's counted properly
|
||||||
@@ -268,13 +268,15 @@ func TestDeltasMulti(t *testing.T) {
|
|||||||
|
|
||||||
doc, err := w.CH.editSession("content/" + title + ".md")
|
doc, err := w.CH.editSession("content/" + title + ".md")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal("couldn't establish docref:", err)
|
t.Fatal("couldn't establish edit session:", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
go w.CH.handleDeltaConn(clients[0], doc)
|
go w.CH.handleDeltaConn(clients[0], doc)
|
||||||
go w.CH.handleDeltaConn(clients[1], doc)
|
go w.CH.handleDeltaConn(clients[1], doc)
|
||||||
go w.CH.handleDeltaConn(clients[2], doc)
|
go w.CH.handleDeltaConn(clients[2], doc)
|
||||||
|
|
||||||
|
time.Sleep(100 * time.Millisecond)
|
||||||
|
|
||||||
a := acedoc.Insert(0, 0, "a")
|
a := acedoc.Insert(0, 0, "a")
|
||||||
b := acedoc.Insert(0, 0, "b")
|
b := acedoc.Insert(0, 0, "b")
|
||||||
c := acedoc.Insert(0, 0, "c")
|
c := acedoc.Insert(0, 0, "c")
|
||||||
@@ -283,12 +285,13 @@ func TestDeltasMulti(t *testing.T) {
|
|||||||
clients[1].ReceiveJSON(w.CH.Message(b))
|
clients[1].ReceiveJSON(w.CH.Message(b))
|
||||||
clients[2].ReceiveJSON(w.CH.Message(c))
|
clients[2].ReceiveJSON(w.CH.Message(c))
|
||||||
|
|
||||||
time.Sleep(400 * time.Millisecond)
|
time.Sleep(1000 * time.Millisecond)
|
||||||
|
|
||||||
for i, client := range clients {
|
for i, client := range clients {
|
||||||
client.mtx.Lock()
|
client.mtx.Lock()
|
||||||
// all clients should have "written" 2 deltas (could be the same
|
t.Logf("client %d exists", i)
|
||||||
// message) that came from the other clients
|
// all clients should have "written" 2 deltas out to their "browser"
|
||||||
|
// that came from the other clients
|
||||||
if len(client.wroteDeltas) != 2 {
|
if len(client.wroteDeltas) != 2 {
|
||||||
t.Errorf("client %d wrote %d deltas, should have written 2", i, len(client.wroteDeltas))
|
t.Errorf("client %d wrote %d deltas, should have written 2", i, len(client.wroteDeltas))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,7 +52,6 @@ func writeThemeFiles(dir string) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
fmt.Println("writing", path.Join(dir, asset))
|
|
||||||
f, err := os.Create(path.Join(dir, asset))
|
f, err := os.Create(path.Join(dir, asset))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|||||||
Reference in New Issue
Block a user