Skip to content

Commit

Permalink
massive with context (#189)
Browse files Browse the repository at this point in the history
  • Loading branch information
ddddddO authored Jun 30, 2023
1 parent c798e9e commit 6c66a9b
Show file tree
Hide file tree
Showing 10 changed files with 68 additions and 47 deletions.
6 changes: 4 additions & 2 deletions cmd/gtree/main.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package main

import (
"context"
"errors"
"fmt"
"log"
Expand Down Expand Up @@ -193,7 +194,8 @@ func actionOutput(c *cli.Context) error {
}
options := []gtree.Option{oi, oo}
if c.Bool("massive") {
options = append(options, gtree.WithMassive())
// TODO: ほぼいらないけど、タイムアウト値をフラグで取ってcontext.WithTimeout渡すようにするでもいいかも
options = append(options, gtree.WithMassive(context.Background()))
}

markdownPath := c.Path("file")
Expand Down Expand Up @@ -243,7 +245,7 @@ func actionMkdir(c *cli.Context) error {
oe := gtree.WithFileExtensions(c.StringSlice("extension"))
options := []gtree.Option{oi, oe}
if c.Bool("massive") {
options = append(options, gtree.WithMassive())
options = append(options, gtree.WithMassive(context.Background()))
}

if c.Bool("dry-run") {
Expand Down
10 changes: 9 additions & 1 deletion config.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
package gtree

import "context"

type config struct {
lastNodeFormat branchFormat
intermedialNodeFormat branchFormat

space spaceType
massive bool
ctx context.Context
encode encode
dryrun bool
fileExtensions []string
Expand Down Expand Up @@ -68,9 +71,14 @@ func WithBranchFormatLastNode(directly, indirectly string) Option {
}

// WithMassive returns function for large amount roots.
func WithMassive() Option {
func WithMassive(ctx context.Context) Option {
return func(c *config) {
c.massive = true

if ctx == nil {
ctx = context.Background()
}
c.ctx = ctx
}
}

Expand Down
31 changes: 15 additions & 16 deletions input_spliter.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,30 +20,29 @@ func split(ctx context.Context, r io.Reader) (<-chan string, <-chan error) {
close(errc)
}()

for {
block := ""
for sc.Scan() {
select {
case <-ctx.Done():
errc <- ctx.Err()
return
default:
block := ""
for sc.Scan() {
l := sc.Text()
if isRootBlockBeginning(l) {
if len(block) != 0 {
blockc <- block
}
block = ""
l := sc.Text()
if isRootBlockBeginning(l) {
if len(block) != 0 {
blockc <- block
}
block += fmt.Sprintln(l)
block = ""
}
if err := sc.Err(); err != nil {
errc <- err
return
}
blockc <- block // 最後のRootブロック送出
return
block += fmt.Sprintln(l)
}
}
if err := sc.Err(); err != nil {
errc <- err
return
}
blockc <- block // 最後のRootブロック送出
return
}()

return blockc, errc
Expand Down
35 changes: 20 additions & 15 deletions pipeline_tree.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,18 +54,18 @@ func newTreePipeline(conf *config) iTree {
}

func (t *treePipeline) output(w io.Writer, r io.Reader, conf *config) error {
ctx, cancel := context.WithCancel(context.Background())
ctx, cancel := context.WithCancel(conf.ctx)
defer cancel()

splitStream, errcsl := split(ctx, r)
rootStream, errcr := newRootGeneratorPipeline(conf.space).generate(ctx, splitStream)
growStream, errcg := t.grow(ctx, rootStream)
errcs := t.spread(ctx, w, growStream)
return t.handlePipelineErr(errcsl, errcr, errcg, errcs)
return t.handlePipelineErr(ctx, errcsl, errcr, errcg, errcs)
}

func (t *treePipeline) outputProgrammably(w io.Writer, root *Node, conf *config) error {
ctx, cancel := context.WithCancel(context.Background())
ctx, cancel := context.WithCancel(conf.ctx)
defer cancel()

rootStream := make(chan *Node)
Expand All @@ -75,22 +75,22 @@ func (t *treePipeline) outputProgrammably(w io.Writer, root *Node, conf *config)
}()
growStream, errcg := t.grow(ctx, rootStream)
errcs := t.spread(ctx, w, growStream)
return t.handlePipelineErr(errcg, errcs)
return t.handlePipelineErr(ctx, errcg, errcs)
}

func (t *treePipeline) makedir(r io.Reader, conf *config) error {
ctx, cancel := context.WithCancel(context.Background())
ctx, cancel := context.WithCancel(conf.ctx)
defer cancel()

splitStream, errcsl := split(ctx, r)
rootStream, errcr := newRootGeneratorPipeline(conf.space).generate(ctx, splitStream)
growStream, errcg := t.grow(ctx, rootStream)
errcm := t.mkdir(ctx, growStream)
return t.handlePipelineErr(errcsl, errcr, errcg, errcm)
return t.handlePipelineErr(ctx, errcsl, errcr, errcg, errcm)
}

func (t *treePipeline) makedirProgrammably(root *Node, conf *config) error {
ctx, cancel := context.WithCancel(context.Background())
ctx, cancel := context.WithCancel(conf.ctx)
defer cancel()

rootStream := make(chan *Node)
Expand All @@ -104,11 +104,11 @@ func (t *treePipeline) makedirProgrammably(root *Node, conf *config) error {
if conf.dryrun {
// when detected no invalid node name, output tree.
errcs := t.spread(ctx, color.Output, growStream)
return t.handlePipelineErr(errcg, errcs)
return t.handlePipelineErr(ctx, errcg, errcs)
}
// when detected no invalid node name, no output tree.
errcm := t.mkdir(ctx, growStream)
return t.handlePipelineErr(errcg, errcm)
return t.handlePipelineErr(ctx, errcg, errcm)
}

// 関心事は各ノードの枝の形成
Expand Down Expand Up @@ -141,17 +141,22 @@ func (t *treePipeline) mkdir(ctx context.Context, roots <-chan *Node) <-chan err
}

// パイプラインの全ステージで最初のエラーを返却
func (*treePipeline) handlePipelineErr(echs ...<-chan error) error {
eg, _ := errgroup.WithContext(context.TODO())
func (*treePipeline) handlePipelineErr(ctx context.Context, echs ...<-chan error) error {
eg, ectx := errgroup.WithContext(ctx)
for i := range echs {
i := i
eg.Go(func() error {
for e := range echs[i] {
if e != nil {
return e
for {
select {
case err := <-echs[i]:
if err != nil {
return err
}
return nil
case <-ectx.Done():
return ectx.Err()
}
}
return nil
})
}
return eg.Wait()
Expand Down
4 changes: 3 additions & 1 deletion pipeline_tree_spreader.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,9 @@ func (ds *defaultSpreaderPipeline) worker(ctx context.Context, wg *sync.WaitGrou
_, err := bw.WriteString(ret)
ds.Unlock()

errc <- err
if err != nil {
errc <- err
}
}
}
}
Expand Down
3 changes: 2 additions & 1 deletion testutil/benchmark_util.go
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
package testutil

import (
"context"
"strings"
"testing"

"github.com/ddddddO/gtree"
)

func BaseBenchmarkWithMassive(roots string, b *testing.B) {
BaseBenchmark(roots, b, gtree.WithMassive())
BaseBenchmark(roots, b, gtree.WithMassive(context.Background()))
}

func BaseBenchmark(roots string, b *testing.B, options ...gtree.Option) {
Expand Down
5 changes: 3 additions & 2 deletions tree_handler_mkdir_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package gtree_test

import (
"context"
"errors"
"strings"
"testing"
Expand Down Expand Up @@ -48,7 +49,7 @@ func TestMkdir(t *testing.T) {
- bb
- lll
-ff`)),
options: []gtree.Option{gtree.WithMassive()},
options: []gtree.Option{gtree.WithMassive(context.Background())},
},
wantErr: gtree.ErrExistPath,
},
Expand Down Expand Up @@ -131,7 +132,7 @@ func TestMkdir(t *testing.T) {
- lll`)),
options: []gtree.Option{
gtree.WithFileExtensions([]string{".go"}),
gtree.WithMassive(),
gtree.WithMassive(context.Background()),
},
},
wantErr: nil,
Expand Down
15 changes: 8 additions & 7 deletions tree_handler_output_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package gtree_test
import (
"bufio"
"bytes"
"context"
"errors"
"fmt"
"io"
Expand Down Expand Up @@ -348,7 +349,7 @@ a
- e
- o
- g`)),
options: []gtree.Option{gtree.WithMassive()},
options: []gtree.Option{gtree.WithMassive(context.Background())},
},
out: out{
output: strings.TrimPrefix(`
Expand Down Expand Up @@ -417,7 +418,7 @@ a
input: strings.NewReader(strings.TrimSpace(fmt.Sprintf(`
- a
- %s`, strings.Repeat("a", 64*1024)))),
options: []gtree.Option{gtree.WithMassive()},
options: []gtree.Option{gtree.WithMassive(context.Background())},
},
out: out{
output: "",
Expand Down Expand Up @@ -560,7 +561,7 @@ a prev tab
- b
- c`)),
options: []gtree.Option{
gtree.WithMassive(),
gtree.WithMassive(context.Background()),
},
},
out: out{
Expand All @@ -583,7 +584,7 @@ a
- c
- y`)),
options: []gtree.Option{
gtree.WithMassive(),
gtree.WithMassive(context.Background()),
gtree.WithDryRun(),
gtree.WithFileExtensions([]string{"c"}),
},
Expand All @@ -610,7 +611,7 @@ a
- b
- c`)),
options: []gtree.Option{
gtree.WithMassive(),
gtree.WithMassive(context.Background()),
gtree.WithEncodeJSON(),
},
},
Expand All @@ -628,7 +629,7 @@ a
- b
- c`)),
options: []gtree.Option{
gtree.WithMassive(),
gtree.WithMassive(context.Background()),
gtree.WithEncodeYAML(),
},
},
Expand All @@ -653,7 +654,7 @@ children:
- b
- c`)),
options: []gtree.Option{
gtree.WithMassive(),
gtree.WithMassive(context.Background()),
gtree.WithEncodeTOML(),
},
},
Expand Down
3 changes: 2 additions & 1 deletion tree_handler_programmably_mkdir_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package gtree_test

import (
"context"
"fmt"
"testing"

Expand All @@ -22,7 +23,7 @@ func TestMkdirProgrammably(t *testing.T) {
{
name: "case(succeeded/massive)",
root: tu.Prepare_a(),
options: []gtree.Option{gtree.WithMassive()},
options: []gtree.Option{gtree.WithMassive(context.Background())},
},
{
name: "case(not root)",
Expand Down
3 changes: 2 additions & 1 deletion tree_handler_programmably_output_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package gtree_test

import (
"bytes"
"context"
"fmt"
"os"
"strings"
Expand Down Expand Up @@ -59,7 +60,7 @@ root
{
name: "case(succeeded/massive)",
root: tu.Prepare(),
options: []gtree.Option{gtree.WithMassive()},
options: []gtree.Option{gtree.WithMassive(context.Background())},
want: strings.TrimPrefix(`
root
└── child 1
Expand Down

0 comments on commit 6c66a9b

Please sign in to comment.