diff --git a/internal/app/index.go b/internal/app/index.go
index 894563e..eea3c25 100644
--- a/internal/app/index.go
+++ b/internal/app/index.go
@@ -8,7 +8,7 @@ import (
)
type model struct {
- Message deferrable.Defer[chan []string]
+ Message deferrable.Value[[]string]
}
func Index(addArtificialDelay bool) http.HandlerFunc {
@@ -27,6 +27,6 @@ func Index(addArtificialDelay bool) http.HandlerFunc {
close(data)
}()
- _ = websupport.Render(w, Resources, "index", model{Message: deferrable.New(w, data)})
+ _ = websupport.Render(w, Resources, "index", model{Message: deferrable.NewValue(w, data)})
}
}
diff --git a/internal/app/resources/templates/index.gohtml b/internal/app/resources/templates/index.gohtml
index 2bf1aa8..d484b06 100644
--- a/internal/app/resources/templates/index.gohtml
+++ b/internal/app/resources/templates/index.gohtml
@@ -19,17 +19,16 @@
- {{ range $items := .Message.Value }}
-
-
- Success!
-
+ {{ $items := .Message.Get }}
+
+
+ Success!
+
-
- {{range $item := $items}}
- - {{$item}}
- {{end}}
-
-
- {{ end }}
+
+ {{range $item := $items}}
+ - {{$item}}
+ {{end}}
+
+
{{- end}}
diff --git a/pkg/deferrable/deferrable.go b/pkg/deferrable/deferrable.go
deleted file mode 100644
index 73a9ce9..0000000
--- a/pkg/deferrable/deferrable.go
+++ /dev/null
@@ -1,20 +0,0 @@
-package deferrable
-
-import "net/http"
-
-type Defer[T any] struct {
- writer http.ResponseWriter
- value T
-}
-
-func New[T any](writer http.ResponseWriter, value T) Defer[T] {
- return Defer[T]{
- writer: writer,
- value: value,
- }
-}
-
-func (d Defer[T]) Value() T {
- _ = http.NewResponseController(d.writer).Flush()
- return d.value
-}
diff --git a/pkg/deferrable/deferrable_test.go b/pkg/deferrable/deferrable_test.go
deleted file mode 100644
index 484e91d..0000000
--- a/pkg/deferrable/deferrable_test.go
+++ /dev/null
@@ -1,37 +0,0 @@
-package deferrable_test
-
-import (
- "github.com/initialcapacity/go-streaming/pkg/deferrable"
- "github.com/stretchr/testify/assert"
- "net/http"
- "testing"
-)
-
-func TestDefer(t *testing.T) {
- writer := ResponseWriterSpy{}
- d := deferrable.New(&writer, "pickles")
-
- value := d.Value()
-
- assert.Equal(t, "pickles", value)
- assert.True(t, writer.FlushCalled)
-}
-
-type ResponseWriterSpy struct {
- FlushCalled bool
-}
-
-func (w *ResponseWriterSpy) Header() http.Header {
- return map[string][]string{}
-}
-
-func (w *ResponseWriterSpy) Write([]byte) (int, error) {
- return 0, nil
-}
-
-func (w *ResponseWriterSpy) WriteHeader(statusCode int) {
-}
-
-func (w *ResponseWriterSpy) Flush() {
- w.FlushCalled = true
-}
diff --git a/pkg/deferrable/flush.go b/pkg/deferrable/flush.go
new file mode 100644
index 0000000..69884ed
--- /dev/null
+++ b/pkg/deferrable/flush.go
@@ -0,0 +1,7 @@
+package deferrable
+
+import "net/http"
+
+func Flush(w http.ResponseWriter) error {
+ return http.NewResponseController(w).Flush()
+}
diff --git a/pkg/deferrable/range.go b/pkg/deferrable/range.go
new file mode 100644
index 0000000..c789d37
--- /dev/null
+++ b/pkg/deferrable/range.go
@@ -0,0 +1,31 @@
+package deferrable
+
+import "net/http"
+
+type Range[T any] struct {
+ writer http.ResponseWriter
+ channel chan T
+}
+
+func NewRange[T any](writer http.ResponseWriter, channel chan T) Range[T] {
+ return Range[T]{
+ writer: writer,
+ channel: channel,
+ }
+}
+
+func (d Range[T]) Get() chan T {
+ _ = Flush(d.writer)
+ flushChannel := make(chan T)
+
+ go func() {
+ for val := range d.channel {
+ _ = Flush(d.writer)
+ flushChannel <- val
+ }
+ _ = Flush(d.writer)
+ close(flushChannel)
+ }()
+
+ return flushChannel
+}
diff --git a/pkg/deferrable/range_test.go b/pkg/deferrable/range_test.go
new file mode 100644
index 0000000..4db09b2
--- /dev/null
+++ b/pkg/deferrable/range_test.go
@@ -0,0 +1,26 @@
+package deferrable_test
+
+import (
+ "github.com/initialcapacity/go-streaming/pkg/deferrable"
+ "github.com/initialcapacity/go-streaming/pkg/deferrable/test"
+ "github.com/stretchr/testify/assert"
+ "testing"
+)
+
+func TestRange(t *testing.T) {
+ writer := deferrable_test.ResponseWriterSpy{}
+ channel := make(chan string)
+ defer close(channel)
+
+ go func() {
+ channel <- "pickles"
+ channel <- "chicken"
+ }()
+
+ values := deferrable.NewRange(&writer, channel).Get()
+
+ assert.Equal(t, uint64(1), writer.FlushCalls.Load())
+ assert.Equal(t, "pickles", <-values)
+ assert.Equal(t, "chicken", <-values)
+ assert.Equal(t, uint64(3), writer.FlushCalls.Load())
+}
diff --git a/pkg/deferrable/test/response_writer_spy.go b/pkg/deferrable/test/response_writer_spy.go
new file mode 100644
index 0000000..e49d310
--- /dev/null
+++ b/pkg/deferrable/test/response_writer_spy.go
@@ -0,0 +1,25 @@
+package deferrable_test
+
+import (
+ "net/http"
+ "sync/atomic"
+)
+
+type ResponseWriterSpy struct {
+ FlushCalls atomic.Uint64
+}
+
+func (w *ResponseWriterSpy) Header() http.Header {
+ return map[string][]string{}
+}
+
+func (w *ResponseWriterSpy) Write([]byte) (int, error) {
+ return 0, nil
+}
+
+func (w *ResponseWriterSpy) WriteHeader(_ int) {
+}
+
+func (w *ResponseWriterSpy) Flush() {
+ w.FlushCalls.Add(1)
+}
diff --git a/pkg/deferrable/value.go b/pkg/deferrable/value.go
new file mode 100644
index 0000000..2cb20c6
--- /dev/null
+++ b/pkg/deferrable/value.go
@@ -0,0 +1,20 @@
+package deferrable
+
+import "net/http"
+
+type Value[T any] struct {
+ writer http.ResponseWriter
+ channel chan T
+}
+
+func NewValue[T any](writer http.ResponseWriter, channel chan T) Value[T] {
+ return Value[T]{
+ writer: writer,
+ channel: channel,
+ }
+}
+
+func (d Value[T]) Get() T {
+ _ = Flush(d.writer)
+ return <-d.channel
+}
diff --git a/pkg/deferrable/value_test.go b/pkg/deferrable/value_test.go
new file mode 100644
index 0000000..dc940de
--- /dev/null
+++ b/pkg/deferrable/value_test.go
@@ -0,0 +1,23 @@
+package deferrable_test
+
+import (
+ "github.com/initialcapacity/go-streaming/pkg/deferrable"
+ "github.com/initialcapacity/go-streaming/pkg/deferrable/test"
+ "github.com/stretchr/testify/assert"
+ "testing"
+)
+
+func TestChannel(t *testing.T) {
+ writer := deferrable_test.ResponseWriterSpy{}
+ channel := make(chan string)
+ defer close(channel)
+
+ go func() {
+ channel <- "pickles"
+ }()
+
+ value := deferrable.NewValue(&writer, channel).Get()
+
+ assert.Equal(t, "pickles", value)
+ assert.Equal(t, uint64(1), writer.FlushCalls.Load())
+}