|
1 | 1 | package golibmc |
2 | 2 |
|
3 | 3 | import ( |
| 4 | + "sync" |
4 | 5 | "context" |
5 | 6 | "fmt" |
6 | 7 | "strconv" |
@@ -1002,3 +1003,79 @@ func testFlushAll(mc *Client, t *testing.T) { |
1002 | 1003 | } |
1003 | 1004 |
|
1004 | 1005 | } |
| 1006 | + |
| 1007 | +func getSlowMc() *Client { |
| 1008 | + servers := make([]string, 1) |
| 1009 | + servers[0] = fmt.Sprintf("localhost:%d", 8965) |
| 1010 | + noreply := false |
| 1011 | + hashFunc := HashCRC32 |
| 1012 | + failover := false |
| 1013 | + disableLock := false |
| 1014 | + |
| 1015 | + mc := New(servers, noreply, "", hashFunc, failover, disableLock) |
| 1016 | + |
| 1017 | + // slow mc response in 500ms, larger than default poll (300ms) |
| 1018 | + mc.ConfigTimeout(PollTimeout, 800*time.Millisecond) |
| 1019 | + return mc |
| 1020 | + |
| 1021 | +} |
| 1022 | + |
| 1023 | +func TestSlowMemcacheStuck(t *testing.T) { |
| 1024 | + mc := getSlowMc() |
| 1025 | + |
| 1026 | + key := "key" |
| 1027 | + mc.Set(context.Background(), &Item{Key: key, Value: []byte("99")}) |
| 1028 | + |
| 1029 | + var wg sync.WaitGroup |
| 1030 | + for i := 1; i < 10; i++ { |
| 1031 | + wg.Add(1) |
| 1032 | + go func(mc *Client, key string, counter int, wg *sync.WaitGroup) { |
| 1033 | + startTime := time.Now() |
| 1034 | + _, err := mc.Get(context.Background(), key) |
| 1035 | + elapsedTime := time.Since(startTime) // Calculate the elapsed time |
| 1036 | + fmt.Printf("%d runs in: %s\n", counter, elapsedTime) |
| 1037 | + if err != nil { |
| 1038 | + t.Errorf("%d mc get error: %s\n", counter, err) |
| 1039 | + } else if counter > 1 && elapsedTime < 1*time.Second { |
| 1040 | + t.Errorf("%d runs fast: %s\n", counter, elapsedTime) |
| 1041 | + } |
| 1042 | + wg.Done() |
| 1043 | + }(mc, key, i, &wg) |
| 1044 | + // give a go for prev goroutine |
| 1045 | + time.Sleep(10 * time.Millisecond) |
| 1046 | + } |
| 1047 | + wg.Wait() |
| 1048 | +} |
| 1049 | + |
| 1050 | +func TestSlowMemcache(t *testing.T) { |
| 1051 | + mc := getSlowMc() |
| 1052 | + |
| 1053 | + key := "key" |
| 1054 | + mc.Set(context.Background(), &Item{Key: key, Value: []byte("99")}) |
| 1055 | + |
| 1056 | + var wg sync.WaitGroup |
| 1057 | + for i := 1; i < 10; i++ { |
| 1058 | + wg.Add(1) |
| 1059 | + go func(mc *Client, key string, counter int, wg *sync.WaitGroup) { |
| 1060 | + startTime := time.Now() |
| 1061 | + ctx, cancel := context.WithTimeout(context.Background(), 100*time.Millisecond) |
| 1062 | + defer cancel() |
| 1063 | + _, err := mc.Get(ctx, key) |
| 1064 | + elapsedTime := time.Since(startTime) // Calculate the elapsed time |
| 1065 | + if err == nil { |
| 1066 | + if counter != 1 { |
| 1067 | + t.Errorf("%d mc get value within time: %s\n", counter, elapsedTime) |
| 1068 | + } |
| 1069 | + } else { |
| 1070 | + if elapsedTime > 420*time.Millisecond { |
| 1071 | + t.Errorf("%d stuck fast: %s\n", counter, elapsedTime) |
| 1072 | + } |
| 1073 | + |
| 1074 | + } |
| 1075 | + wg.Done() |
| 1076 | + }(mc, key, i, &wg) |
| 1077 | + // give a go for prev goroutine |
| 1078 | + time.Sleep(10 * time.Millisecond) |
| 1079 | + } |
| 1080 | + wg.Wait() |
| 1081 | +} |
0 commit comments