From 2f0ddc2dc8607e5c8fdd3b10f5cc1712906b2f48 Mon Sep 17 00:00:00 2001 From: Christian Pointner Date: Sun, 7 May 2017 21:20:08 +0200 Subject: added stateful encoder --- src/hub/src/spreadspace.org/sfive/s5cvt.go | 24 +++++++++++++++ src/hub/src/spreadspace.org/sfive/s5cvt_test.go | 36 +++++++++++++++++++++++ src/hub/src/spreadspace.org/sfive/s5srvForward.go | 6 ++-- src/hub/src/spreadspace.org/sfive/s5srvWeb.go | 8 ++--- 4 files changed, 66 insertions(+), 8 deletions(-) (limited to 'src/hub') diff --git a/src/hub/src/spreadspace.org/sfive/s5cvt.go b/src/hub/src/spreadspace.org/sfive/s5cvt.go index 1a8e1f3..9db899c 100644 --- a/src/hub/src/spreadspace.org/sfive/s5cvt.go +++ b/src/hub/src/spreadspace.org/sfive/s5cvt.go @@ -119,6 +119,7 @@ type Encoder interface { Slug() string } +// stateless protocol interfaces type StatelessEncoder struct { enc *json.Encoder } @@ -136,3 +137,26 @@ func (se *StatelessEncoder) Encode(data DataUpdateFull) error { data.StartTime = data.StartTime.UTC() return se.enc.Encode(data) } + +// stateful protocol interfaces +type StatefulEncoder struct { + enc *json.Encoder + Header +} + +func NewStatefulEncoder(w io.Writer) (Encoder, error) { + res := &StatefulEncoder{} + res.Version = ProtocolVersion + res.enc = json.NewEncoder(w) + return res, res.enc.Encode(&res) +} + +func (se *StatefulEncoder) Slug() string { + return "" +} + +func (se *StatefulEncoder) Encode(data DataUpdateFull) error { + data.Version = 0 // the init message took care of that + data.StartTime = data.StartTime.UTC() + return se.enc.Encode(data) +} diff --git a/src/hub/src/spreadspace.org/sfive/s5cvt_test.go b/src/hub/src/spreadspace.org/sfive/s5cvt_test.go index 2b102d5..b44c628 100644 --- a/src/hub/src/spreadspace.org/sfive/s5cvt_test.go +++ b/src/hub/src/spreadspace.org/sfive/s5cvt_test.go @@ -182,3 +182,39 @@ func TestEncodeStateless(t *testing.T) { t.Fatalf("encoding failed:\n actual: %v\n expected: %v\n", decoded, expected) } } + +func TestEncodeStateful(t *testing.T) { + var td DataUpdateFull + td.CopyFromSourceId(&initDataStruct) + td.CopyFromUpdate(&updateDataStruct) + + encoded := &bytes.Buffer{} + enc, err := NewStatefulEncoder(encoded) + if err != nil { + t.Fatalf("encoding init message failed: %v", err) + } + if err := enc.Encode(td); err != nil { + t.Fatalf("encoding data message failed: %v", err) + } + + // check the slug + if enc.Slug() != "" { + t.Fatalf("the slug of a stateful encoder should be the empty string") + } + + // try to decode encoded message + dec, err := NewStatefulDecoder(encoded) + if err != nil { + t.Fatalf("decoding init message failed: %v", err) + } + decoded, err := dec.Decode() + if err != nil { + t.Fatalf("decoding data message failed: %v", err) + } + + expected := td + expected.Version = ProtocolVersion + if !reflect.DeepEqual(decoded, expected) { + t.Fatalf("encoding failed:\n actual: %v\n expected: %v\n", decoded, expected) + } +} diff --git a/src/hub/src/spreadspace.org/sfive/s5srvForward.go b/src/hub/src/spreadspace.org/sfive/s5srvForward.go index 10e4b9d..e88a79d 100644 --- a/src/hub/src/spreadspace.org/sfive/s5srvForward.go +++ b/src/hub/src/spreadspace.org/sfive/s5srvForward.go @@ -107,14 +107,14 @@ tryResync: continue nextBatch } - // TODO: use StatefulEncoder + // TODO: directly write to client body buf := &bytes.Buffer{} - if err := json.NewEncoder(buf).Encode(Header{Version: 1}); err != nil { + enc, err := NewStatefulEncoder(buf) + if err != nil { s5l.Printf("fwd: failed encoding init message: %v\n", err) time.Sleep(500 * time.Millisecond) continue nextBatch } - enc := NewStatelessEncoder(buf) for _, upd := range updates { if err := enc.Encode(upd); err != nil { s5l.Printf("fwd: failed encoding updates: %v\n", err) diff --git a/src/hub/src/spreadspace.org/sfive/s5srvWeb.go b/src/hub/src/spreadspace.org/sfive/s5srvWeb.go index ee9f131..962187f 100644 --- a/src/hub/src/spreadspace.org/sfive/s5srvWeb.go +++ b/src/hub/src/spreadspace.org/sfive/s5srvWeb.go @@ -203,13 +203,11 @@ func webUpdatesGetBulk(srv *Server, w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") // this is actually multiple json documents... w.WriteHeader(http.StatusOK) - // TODO: use StatefulEncoder - if err := json.NewEncoder(w).Encode(Header{Version: 1}); err != nil { - s5l.Printf("Error while sending data: %v", err) + encoder, err := NewStatefulEncoder(w) + if err != nil { + s5l.Printf("Error while sending init: %v", err) return - s5l.Printf("fwd: failed encoding init message: %v\n", err) } - encoder := NewStatelessEncoder(w) for _, upd := range upds { if err := encoder.Encode(upd); err != nil { s5l.Printf("Error while sending data: %v", err) -- cgit v1.2.3