build/maintner/netsource_test.go

384 строки
9.9 KiB
Go
Исходник Обычный вид История

// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package maintner
import (
"context"
"fmt"
"reflect"
"testing"
)
func TestSumSegSize(t *testing.T) {
tests := []struct {
in []fileSeg
want int64
}{
{
in: []fileSeg{fileSeg{size: 1}},
want: 1,
},
{
in: []fileSeg{fileSeg{size: 1}, fileSeg{size: 100}},
want: 101,
},
{
in: nil,
want: 0,
},
}
for i, tt := range tests {
got := sumSegSize(tt.in)
if got != tt.want {
t.Errorf("%d. sumSegSize = %v; want %v", i, got, tt.want)
}
}
}
func TestSumCommonPrefixSize(t *testing.T) {
tests := []struct {
a, b []fileSeg
summer func(file string, n int64) string
want int64
}{
{
a: []fileSeg{fileSeg{size: 1, sha224: "abab"}},
b: []fileSeg{fileSeg{size: 1, sha224: "abab"}},
want: 1,
},
{
a: []fileSeg{fileSeg{size: 1, sha224: "abab"}},
b: []fileSeg{fileSeg{size: 1, sha224: "eeee"}},
want: 0,
},
{
a: []fileSeg{
fileSeg{size: 100, sha224: "abab"},
fileSeg{size: 100, sha224: "abab", file: "a.mutlog"},
},
b: []fileSeg{
fileSeg{size: 100, sha224: "abab"},
fileSeg{size: 50, sha224: "cccc"},
},
summer: func(file string, n int64) string {
if file == "a.mutlog" && n == 50 {
return "cccc"
}
return "xxx"
},
want: 150,
},
{
a: []fileSeg{
fileSeg{size: 100, sha224: "abab"},
fileSeg{size: 50, sha224: "cccc"},
},
b: []fileSeg{
fileSeg{size: 100, sha224: "abab"},
fileSeg{size: 100, sha224: "abab", file: "b.mutlog"},
},
summer: func(file string, n int64) string {
if file == "b.mutlog" && n == 50 {
return "cccc"
}
return "xxx"
},
want: 150,
},
}
for i, tt := range tests {
summer := tt.summer
if summer == nil {
summer = func(file string, n int64) string {
t.Errorf("%d. unexpected call to prefix summer for file=%q, n=%v", i, file, n)
return ""
}
}
ns := &netMutSource{
testHookFilePrefixSum224: summer,
}
got := ns.sumCommonPrefixSize(tt.a, tt.b)
if got != tt.want {
t.Errorf("%d. sumCommonPrefixSize = %v; want %v", i, got, tt.want)
}
}
}
func TestTrimLeadingSegBytes(t *testing.T) {
tests := []struct {
in []fileSeg
trim int64
want []fileSeg
}{
{
in: []fileSeg{fileSeg{size: 100}, fileSeg{size: 50}},
trim: 0,
want: []fileSeg{fileSeg{size: 100}, fileSeg{size: 50}},
},
{
in: []fileSeg{fileSeg{size: 100}, fileSeg{size: 50}},
trim: 150,
want: nil,
},
{
in: []fileSeg{fileSeg{size: 100}, fileSeg{size: 50}},
trim: 100,
want: []fileSeg{fileSeg{size: 50}},
},
{
in: []fileSeg{fileSeg{size: 100}, fileSeg{size: 50}},
trim: 25,
want: []fileSeg{fileSeg{size: 100, skip: 25}, fileSeg{size: 50}},
},
}
for i, tt := range tests {
copyIn := append([]fileSeg(nil), tt.in...)
got := trimLeadingSegBytes(tt.in, tt.trim)
if !reflect.DeepEqual(tt.in, copyIn) {
t.Fatalf("%d. trimLeadingSegBytes modified its input", i)
}
if !reflect.DeepEqual(got, tt.want) {
t.Fatalf("%d. trim = %+v; want %+v", i, got, tt.want)
}
}
}
func TestGetNewSegments(t *testing.T) {
type testCase struct {
name string
lastSegs []fileSeg
serverSegs [][]LogSegmentJSON
// prefixSum is the prefix sum to use if called.
// If empty, prefixSum calls are errors.
prefixSum string
maintner: retry network operations that may fail in getNewSegments On the internet, servers generally don't go out of their way to ensure graceful stream shutdowns, preferring to instead rely on the clients to receive a network error and decide to repeat the same request. netMutSource implements the MutationSource interface, whose GetMutations method should return a final MutationStreamEvent event with a non-nil Err only when the mutation source encounters a fatal error. Most callers correctly handle such fatal errors with a log.Fatalln or equivalent. In practice, the netMutSource.getNewSegments method does a lot of work to ensure it doesn't give up unnecessarily soon, so most errors are really fatal. However, it was attempting to rely on HTTP requests to a remote server to always succeed on the first try. That is a mistake. This change augments the getServerSegments and syncSeg methods to annotate errors that they believe might be due to transient network problems, and adds non-zero number of retries to getNewSegments. That is a good layer to retry since it allows throwing away the least amount of successful progress made thus far-much less than completely restarting a maintner-based program and having it reload the corpus. While here, start relying on the maintnerd server having support for long-polling since it was added in 2017 (CL 42871), which simplifies code by allowing the top-level loop and its nesting to be deleted. Updates golang/go#52048. Change-Id: I8148109f97365697beab5575358069adfa095f0e Reviewed-on: https://go-review.googlesource.com/c/build/+/414174 Reviewed-by: Dmitri Shuralyov <dmitshur@google.com> Reviewed-by: Alex Rakoczy <jenny@golang.org> TryBot-Result: Gopher Robot <gobot@golang.org> Run-TryBot: Dmitri Shuralyov <dmitshur@golang.org> Auto-Submit: Dmitri Shuralyov <dmitshur@golang.org>
2022-06-25 20:12:59 +03:00
want []fileSeg
wantSplit bool
wantSumCommon int64
maintner: retry network operations that may fail in getNewSegments On the internet, servers generally don't go out of their way to ensure graceful stream shutdowns, preferring to instead rely on the clients to receive a network error and decide to repeat the same request. netMutSource implements the MutationSource interface, whose GetMutations method should return a final MutationStreamEvent event with a non-nil Err only when the mutation source encounters a fatal error. Most callers correctly handle such fatal errors with a log.Fatalln or equivalent. In practice, the netMutSource.getNewSegments method does a lot of work to ensure it doesn't give up unnecessarily soon, so most errors are really fatal. However, it was attempting to rely on HTTP requests to a remote server to always succeed on the first try. That is a mistake. This change augments the getServerSegments and syncSeg methods to annotate errors that they believe might be due to transient network problems, and adds non-zero number of retries to getNewSegments. That is a good layer to retry since it allows throwing away the least amount of successful progress made thus far-much less than completely restarting a maintner-based program and having it reload the corpus. While here, start relying on the maintnerd server having support for long-polling since it was added in 2017 (CL 42871), which simplifies code by allowing the top-level loop and its nesting to be deleted. Updates golang/go#52048. Change-Id: I8148109f97365697beab5575358069adfa095f0e Reviewed-on: https://go-review.googlesource.com/c/build/+/414174 Reviewed-by: Dmitri Shuralyov <dmitshur@google.com> Reviewed-by: Alex Rakoczy <jenny@golang.org> TryBot-Result: Gopher Robot <gobot@golang.org> Run-TryBot: Dmitri Shuralyov <dmitshur@golang.org> Auto-Submit: Dmitri Shuralyov <dmitshur@golang.org>
2022-06-25 20:12:59 +03:00
wantUnchanged bool
}
tests := []testCase{
{
name: "first_download",
serverSegs: [][]LogSegmentJSON{
[]LogSegmentJSON{
{Number: 1, Size: 100, SHA224: "abc"},
{Number: 2, Size: 200, SHA224: "def"},
},
},
want: []fileSeg{
{seg: 1, size: 100, sha224: "abc", file: "/fake/0001.mutlog"},
{seg: 2, size: 200, sha224: "def", file: "/fake/0002.mutlog"},
},
},
{
name: "incremental_download_growseg", // from first_download, segment 2 grows a bit
lastSegs: []fileSeg{
{seg: 1, size: 100, sha224: "abc", file: "/fake/0001.mutlog"},
{seg: 2, size: 200, sha224: "def", file: "/fake/0002.mutlog"},
},
prefixSum: "def",
serverSegs: [][]LogSegmentJSON{
[]LogSegmentJSON{
{Number: 1, Size: 100, SHA224: "abc"},
{Number: 2, Size: 205, SHA224: "defdef"},
},
},
want: []fileSeg{
{seg: 2, size: 205, sha224: "defdef", skip: 200, file: "/fake/0002.mutlog"},
},
},
{
name: "incremental_download_growseg_and_newseg", // from first_download, segment 2 grows, and segment 3 appears.
lastSegs: []fileSeg{
{seg: 1, size: 100, sha224: "abc", file: "/fake/0001.mutlog"},
{seg: 2, size: 200, sha224: "def", file: "/fake/0002.mutlog"},
},
prefixSum: "def",
serverSegs: [][]LogSegmentJSON{
[]LogSegmentJSON{
{Number: 1, Size: 100, SHA224: "abc"},
{Number: 2, Size: 250, SHA224: "defdef"},
{Number: 3, Size: 300, SHA224: "fff"},
},
},
want: []fileSeg{
{seg: 2, size: 250, sha224: "defdef", skip: 200, file: "/fake/0002.mutlog"},
{seg: 3, size: 300, sha224: "fff", skip: 0, file: "/fake/0003.mutlog"},
},
},
{
name: "incremental_download_newseg", // from first_download, segment 3 appears.
lastSegs: []fileSeg{
{seg: 1, size: 100, sha224: "abc", file: "/fake/0001.mutlog"},
{seg: 2, size: 200, sha224: "def", file: "/fake/0002.mutlog"},
},
serverSegs: [][]LogSegmentJSON{
[]LogSegmentJSON{
{Number: 1, Size: 100, SHA224: "abc"},
{Number: 2, Size: 200, SHA224: "def"},
{Number: 3, Size: 300, SHA224: "fff"},
},
},
want: []fileSeg{
{seg: 3, size: 300, sha224: "fff", skip: 0, file: "/fake/0003.mutlog"},
},
},
{
maintner: retry network operations that may fail in getNewSegments On the internet, servers generally don't go out of their way to ensure graceful stream shutdowns, preferring to instead rely on the clients to receive a network error and decide to repeat the same request. netMutSource implements the MutationSource interface, whose GetMutations method should return a final MutationStreamEvent event with a non-nil Err only when the mutation source encounters a fatal error. Most callers correctly handle such fatal errors with a log.Fatalln or equivalent. In practice, the netMutSource.getNewSegments method does a lot of work to ensure it doesn't give up unnecessarily soon, so most errors are really fatal. However, it was attempting to rely on HTTP requests to a remote server to always succeed on the first try. That is a mistake. This change augments the getServerSegments and syncSeg methods to annotate errors that they believe might be due to transient network problems, and adds non-zero number of retries to getNewSegments. That is a good layer to retry since it allows throwing away the least amount of successful progress made thus far-much less than completely restarting a maintner-based program and having it reload the corpus. While here, start relying on the maintnerd server having support for long-polling since it was added in 2017 (CL 42871), which simplifies code by allowing the top-level loop and its nesting to be deleted. Updates golang/go#52048. Change-Id: I8148109f97365697beab5575358069adfa095f0e Reviewed-on: https://go-review.googlesource.com/c/build/+/414174 Reviewed-by: Dmitri Shuralyov <dmitshur@google.com> Reviewed-by: Alex Rakoczy <jenny@golang.org> TryBot-Result: Gopher Robot <gobot@golang.org> Run-TryBot: Dmitri Shuralyov <dmitshur@golang.org> Auto-Submit: Dmitri Shuralyov <dmitshur@golang.org>
2022-06-25 20:12:59 +03:00
name: "faulty_server_returns_no_new_data",
lastSegs: []fileSeg{
{seg: 1, size: 101, sha224: "abc", file: "/fake/0001.mutlog"},
},
serverSegs: [][]LogSegmentJSON{
[]LogSegmentJSON{
maintner: retry network operations that may fail in getNewSegments On the internet, servers generally don't go out of their way to ensure graceful stream shutdowns, preferring to instead rely on the clients to receive a network error and decide to repeat the same request. netMutSource implements the MutationSource interface, whose GetMutations method should return a final MutationStreamEvent event with a non-nil Err only when the mutation source encounters a fatal error. Most callers correctly handle such fatal errors with a log.Fatalln or equivalent. In practice, the netMutSource.getNewSegments method does a lot of work to ensure it doesn't give up unnecessarily soon, so most errors are really fatal. However, it was attempting to rely on HTTP requests to a remote server to always succeed on the first try. That is a mistake. This change augments the getServerSegments and syncSeg methods to annotate errors that they believe might be due to transient network problems, and adds non-zero number of retries to getNewSegments. That is a good layer to retry since it allows throwing away the least amount of successful progress made thus far-much less than completely restarting a maintner-based program and having it reload the corpus. While here, start relying on the maintnerd server having support for long-polling since it was added in 2017 (CL 42871), which simplifies code by allowing the top-level loop and its nesting to be deleted. Updates golang/go#52048. Change-Id: I8148109f97365697beab5575358069adfa095f0e Reviewed-on: https://go-review.googlesource.com/c/build/+/414174 Reviewed-by: Dmitri Shuralyov <dmitshur@google.com> Reviewed-by: Alex Rakoczy <jenny@golang.org> TryBot-Result: Gopher Robot <gobot@golang.org> Run-TryBot: Dmitri Shuralyov <dmitshur@golang.org> Auto-Submit: Dmitri Shuralyov <dmitshur@golang.org>
2022-06-25 20:12:59 +03:00
{Number: 1, Size: 101, SHA224: "abc"}, // Same as lastSegs, results in unchanged error.
},
[]LogSegmentJSON{
{Number: 1, Size: 101, SHA224: "abc"},
{Number: 2, Size: 102, SHA224: "def"},
},
},
maintner: retry network operations that may fail in getNewSegments On the internet, servers generally don't go out of their way to ensure graceful stream shutdowns, preferring to instead rely on the clients to receive a network error and decide to repeat the same request. netMutSource implements the MutationSource interface, whose GetMutations method should return a final MutationStreamEvent event with a non-nil Err only when the mutation source encounters a fatal error. Most callers correctly handle such fatal errors with a log.Fatalln or equivalent. In practice, the netMutSource.getNewSegments method does a lot of work to ensure it doesn't give up unnecessarily soon, so most errors are really fatal. However, it was attempting to rely on HTTP requests to a remote server to always succeed on the first try. That is a mistake. This change augments the getServerSegments and syncSeg methods to annotate errors that they believe might be due to transient network problems, and adds non-zero number of retries to getNewSegments. That is a good layer to retry since it allows throwing away the least amount of successful progress made thus far-much less than completely restarting a maintner-based program and having it reload the corpus. While here, start relying on the maintnerd server having support for long-polling since it was added in 2017 (CL 42871), which simplifies code by allowing the top-level loop and its nesting to be deleted. Updates golang/go#52048. Change-Id: I8148109f97365697beab5575358069adfa095f0e Reviewed-on: https://go-review.googlesource.com/c/build/+/414174 Reviewed-by: Dmitri Shuralyov <dmitshur@google.com> Reviewed-by: Alex Rakoczy <jenny@golang.org> TryBot-Result: Gopher Robot <gobot@golang.org> Run-TryBot: Dmitri Shuralyov <dmitshur@golang.org> Auto-Submit: Dmitri Shuralyov <dmitshur@golang.org>
2022-06-25 20:12:59 +03:00
wantUnchanged: true,
},
{
name: "split_error_diff_first_seg_same_size",
lastSegs: []fileSeg{
{seg: 1, size: 101, sha224: "abc", file: "/fake/0001.mutlog"},
},
serverSegs: [][]LogSegmentJSON{
[]LogSegmentJSON{
{Number: 1, Size: 101, SHA224: "def"},
},
},
wantSplit: true,
},
{
name: "split_error_diff_first_seg_and_longer",
lastSegs: []fileSeg{
{seg: 1, size: 101, sha224: "abc", file: "/fake/0001.mutlog"},
},
serverSegs: [][]LogSegmentJSON{
[]LogSegmentJSON{
{Number: 1, Size: 102, SHA224: "def"},
},
},
prefixSum: "ffffffffff", // no match
wantSplit: true,
},
{
name: "split_error_diff_first_seg_and_shorter",
lastSegs: []fileSeg{
{seg: 1, size: 101, sha224: "abc", file: "/fake/0001.mutlog"},
},
serverSegs: [][]LogSegmentJSON{
[]LogSegmentJSON{
{Number: 1, Size: 50, SHA224: "def"},
},
},
prefixSum: "ffffffffff", // no match
wantSplit: true,
},
{
name: "split_error_same_first_seg_but_shorter",
lastSegs: []fileSeg{
{seg: 1, size: 101, sha224: "abc", file: "/fake/0001.mutlog"},
},
serverSegs: [][]LogSegmentJSON{
[]LogSegmentJSON{
{Number: 1, Size: 50, SHA224: "def"},
},
},
prefixSum: "def", // match
wantSplit: true,
wantSumCommon: 50,
},
{
name: "split_error_diff_final_seg",
lastSegs: []fileSeg{
{seg: 1, size: 100, sha224: "abc", file: "/fake/0001.mutlog"},
{seg: 2, size: 2, sha224: "def", file: "/fake/0002.mutlog"},
},
serverSegs: [][]LogSegmentJSON{
[]LogSegmentJSON{
{Number: 1, Size: 100, SHA224: "abc"},
{Number: 2, Size: 4, SHA224: "fff"},
},
},
prefixSum: "not_def",
wantSplit: true,
wantSumCommon: 100,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
serverSegCalls := 0
maintner: retry network operations that may fail in getNewSegments On the internet, servers generally don't go out of their way to ensure graceful stream shutdowns, preferring to instead rely on the clients to receive a network error and decide to repeat the same request. netMutSource implements the MutationSource interface, whose GetMutations method should return a final MutationStreamEvent event with a non-nil Err only when the mutation source encounters a fatal error. Most callers correctly handle such fatal errors with a log.Fatalln or equivalent. In practice, the netMutSource.getNewSegments method does a lot of work to ensure it doesn't give up unnecessarily soon, so most errors are really fatal. However, it was attempting to rely on HTTP requests to a remote server to always succeed on the first try. That is a mistake. This change augments the getServerSegments and syncSeg methods to annotate errors that they believe might be due to transient network problems, and adds non-zero number of retries to getNewSegments. That is a good layer to retry since it allows throwing away the least amount of successful progress made thus far-much less than completely restarting a maintner-based program and having it reload the corpus. While here, start relying on the maintnerd server having support for long-polling since it was added in 2017 (CL 42871), which simplifies code by allowing the top-level loop and its nesting to be deleted. Updates golang/go#52048. Change-Id: I8148109f97365697beab5575358069adfa095f0e Reviewed-on: https://go-review.googlesource.com/c/build/+/414174 Reviewed-by: Dmitri Shuralyov <dmitshur@google.com> Reviewed-by: Alex Rakoczy <jenny@golang.org> TryBot-Result: Gopher Robot <gobot@golang.org> Run-TryBot: Dmitri Shuralyov <dmitshur@golang.org> Auto-Submit: Dmitri Shuralyov <dmitshur@golang.org>
2022-06-25 20:12:59 +03:00
syncSegCalls := 0
ns := &netMutSource{
last: tt.lastSegs,
testHookGetServerSegments: func(_ context.Context, waitSizeNot int64) (segs []LogSegmentJSON, err error) {
serverSegCalls++
maintner: retry network operations that may fail in getNewSegments On the internet, servers generally don't go out of their way to ensure graceful stream shutdowns, preferring to instead rely on the clients to receive a network error and decide to repeat the same request. netMutSource implements the MutationSource interface, whose GetMutations method should return a final MutationStreamEvent event with a non-nil Err only when the mutation source encounters a fatal error. Most callers correctly handle such fatal errors with a log.Fatalln or equivalent. In practice, the netMutSource.getNewSegments method does a lot of work to ensure it doesn't give up unnecessarily soon, so most errors are really fatal. However, it was attempting to rely on HTTP requests to a remote server to always succeed on the first try. That is a mistake. This change augments the getServerSegments and syncSeg methods to annotate errors that they believe might be due to transient network problems, and adds non-zero number of retries to getNewSegments. That is a good layer to retry since it allows throwing away the least amount of successful progress made thus far-much less than completely restarting a maintner-based program and having it reload the corpus. While here, start relying on the maintnerd server having support for long-polling since it was added in 2017 (CL 42871), which simplifies code by allowing the top-level loop and its nesting to be deleted. Updates golang/go#52048. Change-Id: I8148109f97365697beab5575358069adfa095f0e Reviewed-on: https://go-review.googlesource.com/c/build/+/414174 Reviewed-by: Dmitri Shuralyov <dmitshur@google.com> Reviewed-by: Alex Rakoczy <jenny@golang.org> TryBot-Result: Gopher Robot <gobot@golang.org> Run-TryBot: Dmitri Shuralyov <dmitshur@golang.org> Auto-Submit: Dmitri Shuralyov <dmitshur@golang.org>
2022-06-25 20:12:59 +03:00
if serverSegCalls%2 == 1 {
return nil, fetchError{PossiblyRetryable: true, Err: fmt.Errorf("fake error to simulate the internet saying 'not this time' every now and then")}
}
if len(tt.serverSegs) == 0 {
return nil, nil
}
segs = tt.serverSegs[0]
if len(tt.serverSegs) > 1 {
tt.serverSegs = tt.serverSegs[1:]
}
return segs, nil
},
testHookSyncSeg: func(_ context.Context, seg LogSegmentJSON) (fileSeg, []byte, error) {
maintner: retry network operations that may fail in getNewSegments On the internet, servers generally don't go out of their way to ensure graceful stream shutdowns, preferring to instead rely on the clients to receive a network error and decide to repeat the same request. netMutSource implements the MutationSource interface, whose GetMutations method should return a final MutationStreamEvent event with a non-nil Err only when the mutation source encounters a fatal error. Most callers correctly handle such fatal errors with a log.Fatalln or equivalent. In practice, the netMutSource.getNewSegments method does a lot of work to ensure it doesn't give up unnecessarily soon, so most errors are really fatal. However, it was attempting to rely on HTTP requests to a remote server to always succeed on the first try. That is a mistake. This change augments the getServerSegments and syncSeg methods to annotate errors that they believe might be due to transient network problems, and adds non-zero number of retries to getNewSegments. That is a good layer to retry since it allows throwing away the least amount of successful progress made thus far-much less than completely restarting a maintner-based program and having it reload the corpus. While here, start relying on the maintnerd server having support for long-polling since it was added in 2017 (CL 42871), which simplifies code by allowing the top-level loop and its nesting to be deleted. Updates golang/go#52048. Change-Id: I8148109f97365697beab5575358069adfa095f0e Reviewed-on: https://go-review.googlesource.com/c/build/+/414174 Reviewed-by: Dmitri Shuralyov <dmitshur@google.com> Reviewed-by: Alex Rakoczy <jenny@golang.org> TryBot-Result: Gopher Robot <gobot@golang.org> Run-TryBot: Dmitri Shuralyov <dmitshur@golang.org> Auto-Submit: Dmitri Shuralyov <dmitshur@golang.org>
2022-06-25 20:12:59 +03:00
syncSegCalls++
if syncSegCalls%3 == 1 {
return fileSeg{}, nil, fetchError{PossiblyRetryable: true, Err: fmt.Errorf("fake error to simulate the internet saying 'not this time' every now and then")}
}
return fileSeg{
seg: seg.Number,
size: seg.Size,
sha224: seg.SHA224,
file: fmt.Sprintf("/fake/%04d.mutlog", seg.Number),
}, nil, nil
},
testHookOnSplit: func(sumCommon int64) {
if got, want := sumCommon, tt.wantSumCommon; got != want {
t.Errorf("sumCommon = %v; want %v", got, want)
}
},
testHookFilePrefixSum224: func(file string, n int64) string {
if tt.prefixSum != "" {
return tt.prefixSum
}
t.Errorf("unexpected call to filePrefixSum224(%q, %d)", file, n)
return "XXXX"
},
}
got, err := ns.getNewSegments(context.Background())
maintner: retry network operations that may fail in getNewSegments On the internet, servers generally don't go out of their way to ensure graceful stream shutdowns, preferring to instead rely on the clients to receive a network error and decide to repeat the same request. netMutSource implements the MutationSource interface, whose GetMutations method should return a final MutationStreamEvent event with a non-nil Err only when the mutation source encounters a fatal error. Most callers correctly handle such fatal errors with a log.Fatalln or equivalent. In practice, the netMutSource.getNewSegments method does a lot of work to ensure it doesn't give up unnecessarily soon, so most errors are really fatal. However, it was attempting to rely on HTTP requests to a remote server to always succeed on the first try. That is a mistake. This change augments the getServerSegments and syncSeg methods to annotate errors that they believe might be due to transient network problems, and adds non-zero number of retries to getNewSegments. That is a good layer to retry since it allows throwing away the least amount of successful progress made thus far-much less than completely restarting a maintner-based program and having it reload the corpus. While here, start relying on the maintnerd server having support for long-polling since it was added in 2017 (CL 42871), which simplifies code by allowing the top-level loop and its nesting to be deleted. Updates golang/go#52048. Change-Id: I8148109f97365697beab5575358069adfa095f0e Reviewed-on: https://go-review.googlesource.com/c/build/+/414174 Reviewed-by: Dmitri Shuralyov <dmitshur@google.com> Reviewed-by: Alex Rakoczy <jenny@golang.org> TryBot-Result: Gopher Robot <gobot@golang.org> Run-TryBot: Dmitri Shuralyov <dmitshur@golang.org> Auto-Submit: Dmitri Shuralyov <dmitshur@golang.org>
2022-06-25 20:12:59 +03:00
if tt.wantSplit {
if err != ErrSplit {
t.Fatalf("wanted ErrSplit; got %+v, %v", got, err)
}
// Success.
return
}
maintner: retry network operations that may fail in getNewSegments On the internet, servers generally don't go out of their way to ensure graceful stream shutdowns, preferring to instead rely on the clients to receive a network error and decide to repeat the same request. netMutSource implements the MutationSource interface, whose GetMutations method should return a final MutationStreamEvent event with a non-nil Err only when the mutation source encounters a fatal error. Most callers correctly handle such fatal errors with a log.Fatalln or equivalent. In practice, the netMutSource.getNewSegments method does a lot of work to ensure it doesn't give up unnecessarily soon, so most errors are really fatal. However, it was attempting to rely on HTTP requests to a remote server to always succeed on the first try. That is a mistake. This change augments the getServerSegments and syncSeg methods to annotate errors that they believe might be due to transient network problems, and adds non-zero number of retries to getNewSegments. That is a good layer to retry since it allows throwing away the least amount of successful progress made thus far-much less than completely restarting a maintner-based program and having it reload the corpus. While here, start relying on the maintnerd server having support for long-polling since it was added in 2017 (CL 42871), which simplifies code by allowing the top-level loop and its nesting to be deleted. Updates golang/go#52048. Change-Id: I8148109f97365697beab5575358069adfa095f0e Reviewed-on: https://go-review.googlesource.com/c/build/+/414174 Reviewed-by: Dmitri Shuralyov <dmitshur@google.com> Reviewed-by: Alex Rakoczy <jenny@golang.org> TryBot-Result: Gopher Robot <gobot@golang.org> Run-TryBot: Dmitri Shuralyov <dmitshur@golang.org> Auto-Submit: Dmitri Shuralyov <dmitshur@golang.org>
2022-06-25 20:12:59 +03:00
if tt.wantUnchanged {
if err == nil || err.Error() != "maintner.netsource: maintnerd server returned unchanged log segments" {
t.Fatalf("wanted unchanged; got %+v, %v", got, err)
}
// Success.
return
}
if err != nil {
t.Fatal(err)
}
if !reflect.DeepEqual(got, tt.want) {
t.Errorf("mismatch\n got: %+v\nwant: %+v\n", got, tt.want)
}
})
}
}