package transform import ( "bytes" "fmt" "io" "gordenko.dev/dima/diploma/bin" "gordenko.dev/dima/diploma/proto" ) // CHUNKED RESPONDER var endMsg = []byte{ proto.RespEndOfValue, // end of stream } type ChunkedResponder struct { recordsQty int buf *bytes.Buffer dst io.Writer } func NewChunkedResponder(dst io.Writer) *ChunkedResponder { s := &ChunkedResponder{ recordsQty: 0, buf: bytes.NewBuffer(nil), dst: dst, } s.buf.Write([]byte{ proto.RespPartOfValue, // message type 0, 0, 0, 0, // records qty }) return s } func (s *ChunkedResponder) BufferRecord(rec []byte) { s.buf.Write(rec) s.recordsQty++ } func (s *ChunkedResponder) AppendRecord(rec []byte) error { s.buf.Write(rec) s.recordsQty++ if s.buf.Len() < 1500 { return nil } if err := s.sendBuffered(); err != nil { return err } s.buf.Write([]byte{ proto.RespPartOfValue, // message type 0, 0, 0, 0, // records qty }) s.recordsQty = 0 return nil } func (s *ChunkedResponder) Flush() error { if s.recordsQty > 0 { if err := s.sendBuffered(); err != nil { return err } } if _, err := s.dst.Write(endMsg); err != nil { return err } //fmt.Printf("sent endMsg %d\n", endMsg) return nil } func (s *ChunkedResponder) sendBuffered() (err error) { msg := s.buf.Bytes() bin.PutUint32(msg[1:], uint32(s.recordsQty)) //fmt.Printf("put uint16: %d\n", msg[:3]) //fmt.Printf("send %d records\n", s.recordsQty) //fmt.Printf("send buffered: %d, qty: %d\n", msg, s.recordsQty) n, err := s.dst.Write(msg) if err != nil { return } if n != len(msg) { return fmt.Errorf("incomplete write %d bytes instead of %d", n, len(msg)) } s.buf.Reset() return } // Для Aggregation пишем функцию определения периода и пуляем фактические периоды // // By default net/http.Server uses 4KB buffers, which are flushed to client with chunked responses. // These buffers may result in visible overhead for responses exceeding a few megabytes. // So allocate 64Kb buffers. // bw: bufio.NewWriterSize(w, 64*1024),