github.com/dtm-labs/rockscache@v0.1.1/batch_test.go (about)

     1  package rockscache
     2  
     3  import (
     4  	"errors"
     5  	"math/rand"
     6  	"strconv"
     7  	"testing"
     8  	"time"
     9  
    10  	"github.com/stretchr/testify/assert"
    11  )
    12  
    13  func genBatchDataFunc(values map[int]string, sleepMilli int) func(idxs []int) (map[int]string, error) {
    14  	return func(idxs []int) (map[int]string, error) {
    15  		debugf("batch fetching: %v", idxs)
    16  		time.Sleep(time.Duration(sleepMilli) * time.Millisecond)
    17  		return values, nil
    18  	}
    19  }
    20  
    21  func genIdxs(to int) (idxs []int) {
    22  	for i := 0; i < to; i++ {
    23  		idxs = append(idxs, i)
    24  	}
    25  	return
    26  }
    27  
    28  func genKeys(idxs []int) (keys []string) {
    29  	for _, i := range idxs {
    30  		suffix := strconv.Itoa(i)
    31  		k := "key" + suffix
    32  		keys = append(keys, k)
    33  	}
    34  	return
    35  }
    36  
    37  func genValues(n int, prefix string) map[int]string {
    38  	values := make(map[int]string)
    39  	for i := 0; i < n; i++ {
    40  		v := prefix + strconv.Itoa(i)
    41  		values[i] = v
    42  	}
    43  	return values
    44  }
    45  
    46  func TestWeakFetchBatch(t *testing.T) {
    47  	clearCache()
    48  	rc := NewClient(rdb, NewDefaultOptions())
    49  	began := time.Now()
    50  	n := int(rand.Int31n(20) + 10)
    51  	idxs := genIdxs(n)
    52  	keys, values1, values2 := genKeys(idxs), genValues(n, "value_"), genValues(n, "eulav_")
    53  	values3 := genValues(n, "vvvv_")
    54  	go func() {
    55  		dc2 := NewClient(rdb, NewDefaultOptions())
    56  		v, err := dc2.FetchBatch(keys, 60*time.Second, genBatchDataFunc(values1, 200))
    57  		assert.Nil(t, err)
    58  		assert.Equal(t, values1, v)
    59  	}()
    60  	time.Sleep(20 * time.Millisecond)
    61  
    62  	v, err := rc.FetchBatch(keys, 60*time.Second, genBatchDataFunc(values2, 200))
    63  	assert.Nil(t, err)
    64  	assert.Equal(t, values1, v)
    65  	assert.True(t, time.Since(began) > time.Duration(150)*time.Millisecond)
    66  
    67  	err = rc.TagAsDeletedBatch(keys)
    68  	assert.Nil(t, err)
    69  
    70  	began = time.Now()
    71  	v, err = rc.FetchBatch(keys, 60*time.Second, genBatchDataFunc(values3, 200))
    72  	assert.Nil(t, err)
    73  	assert.Equal(t, values1, v)
    74  	assert.True(t, time.Since(began) < time.Duration(200)*time.Millisecond)
    75  
    76  	time.Sleep(300 * time.Millisecond)
    77  	v, err = rc.FetchBatch(keys, 60*time.Second, genBatchDataFunc(values3, 200))
    78  	assert.Nil(t, err)
    79  	assert.Equal(t, values3, v)
    80  }
    81  
    82  func TestWeakFetchBatchOverlap(t *testing.T) {
    83  	clearCache()
    84  	rc := NewClient(rdb, NewDefaultOptions())
    85  	began := time.Now()
    86  	n := 100
    87  	idxs := genIdxs(n)
    88  	keys := genKeys(idxs)
    89  	keys1, values1 := keys[:60], genValues(60, "value_")
    90  	keys2, values2 := keys[40:], genValues(60, "eulav_")
    91  
    92  	go func() {
    93  		dc2 := NewClient(rdb, NewDefaultOptions())
    94  		v, err := dc2.FetchBatch(keys1, 60*time.Second, genBatchDataFunc(values1, 200))
    95  		assert.Nil(t, err)
    96  		assert.Equal(t, values1, v)
    97  	}()
    98  	time.Sleep(20 * time.Millisecond)
    99  
   100  	v, err := rc.FetchBatch(keys2, 60*time.Second, genBatchDataFunc(values2, 200))
   101  	assert.Nil(t, err)
   102  	assert.True(t, time.Since(began) > time.Duration(150)*time.Millisecond)
   103  	for i := 40; i < 60; i++ {
   104  		assert.Equal(t, keys2[i-40], keys1[i])
   105  		assert.Equal(t, values1[i], v[i-40])
   106  	}
   107  	for i := 60; i < n; i++ {
   108  		assert.Equal(t, values2[i-40], v[i-40])
   109  	}
   110  
   111  	rc.TagAsDeletedBatch(keys[40:60])
   112  	began = time.Now()
   113  	_, err = rc.FetchBatch(keys2, 60*time.Second, genBatchDataFunc(values2, 200))
   114  	assert.Nil(t, err)
   115  	assert.True(t, time.Since(began) < time.Duration(200)*time.Millisecond)
   116  	for i := 40; i < 60; i++ {
   117  		assert.Equal(t, keys2[i-40], keys1[i])
   118  		assert.Equal(t, values1[i], v[i-40])
   119  	}
   120  	for i := 60; i < n; i++ {
   121  		assert.Equal(t, values2[i-40], v[i-40])
   122  	}
   123  
   124  	time.Sleep(300 * time.Millisecond)
   125  	v, err = rc.FetchBatch(keys2, 20*time.Second, genBatchDataFunc(values2, 200))
   126  	assert.Nil(t, err)
   127  	assert.Equal(t, values2, v)
   128  }
   129  
   130  func TestStrongFetchBatch(t *testing.T) {
   131  	clearCache()
   132  	rc := NewClient(rdb, NewDefaultOptions())
   133  	rc.Options.StrongConsistency = true
   134  	began := time.Now()
   135  	n := int(rand.Int31n(20) + 10)
   136  	idxs := genIdxs(n)
   137  	keys, values1, values2 := genKeys(idxs), genValues(n, "value_"), genValues(n, "eulav_")
   138  	values3, values4 := genValues(n, "vvvv_"), genValues(n, "uuuu_")
   139  	go func() {
   140  		dc2 := NewClient(rdb, NewDefaultOptions())
   141  		v, err := dc2.FetchBatch(keys, 60*time.Second, genBatchDataFunc(values1, 200))
   142  		assert.Nil(t, err)
   143  		assert.Equal(t, values1, v)
   144  	}()
   145  	time.Sleep(20 * time.Millisecond)
   146  
   147  	v, err := rc.FetchBatch(keys, 60*time.Second, genBatchDataFunc(values2, 200))
   148  	assert.Nil(t, err)
   149  	assert.Equal(t, values1, v)
   150  	assert.True(t, time.Since(began) > time.Duration(150)*time.Millisecond)
   151  
   152  	err = rc.TagAsDeletedBatch(keys)
   153  	assert.Nil(t, err)
   154  
   155  	began = time.Now()
   156  	v, err = rc.FetchBatch(keys, 60*time.Second, genBatchDataFunc(values3, 200))
   157  	assert.Nil(t, err)
   158  	assert.Equal(t, values3, v)
   159  	assert.True(t, time.Since(began) > time.Duration(150)*time.Millisecond)
   160  
   161  	v, err = rc.FetchBatch(keys, 60*time.Second, genBatchDataFunc(values4, 200))
   162  	assert.Nil(t, err)
   163  	assert.Equal(t, values3, v)
   164  }
   165  
   166  func TestStrongFetchBatchOverlap(t *testing.T) {
   167  	clearCache()
   168  	rc := NewClient(rdb, NewDefaultOptions())
   169  	rc.Options.StrongConsistency = true
   170  	began := time.Now()
   171  	n := 100
   172  	idxs := genIdxs(n)
   173  	keys := genKeys(idxs)
   174  	keys1, values1 := keys[:60], genValues(60, "value_")
   175  	keys2, values2 := keys[40:], genValues(60, "eulav_")
   176  
   177  	go func() {
   178  		dc2 := NewClient(rdb, NewDefaultOptions())
   179  		v, err := dc2.FetchBatch(keys1, 20*time.Second, genBatchDataFunc(values1, 200))
   180  		assert.Nil(t, err)
   181  		assert.Equal(t, values1, v)
   182  	}()
   183  	time.Sleep(20 * time.Millisecond)
   184  
   185  	v, err := rc.FetchBatch(keys2, 20*time.Second, genBatchDataFunc(values2, 200))
   186  	assert.Nil(t, err)
   187  	assert.True(t, time.Since(began) > time.Duration(150)*time.Millisecond)
   188  	for i := 40; i < 60; i++ {
   189  		assert.Equal(t, keys2[i-40], keys1[i])
   190  		assert.Equal(t, values1[i], v[i-40])
   191  	}
   192  	for i := 60; i < n; i++ {
   193  		assert.Equal(t, values2[i-40], v[i-40])
   194  	}
   195  }
   196  
   197  func TestStrongFetchBatchOverlapExpire(t *testing.T) {
   198  	clearCache()
   199  	opts := NewDefaultOptions()
   200  	opts.Delay = 10 * time.Millisecond
   201  	opts.StrongConsistency = true
   202  
   203  	rc := NewClient(rdb, opts)
   204  	began := time.Now()
   205  	n := 100
   206  	idxs := genIdxs(n)
   207  	keys := genKeys(idxs)
   208  	keys1, values1 := keys[:60], genValues(60, "value_")
   209  	keys2, values2 := keys[40:], genValues(60, "eulav_")
   210  
   211  	v, err := rc.FetchBatch(keys1, 2*time.Second, genBatchDataFunc(values1, 200))
   212  	assert.Nil(t, err)
   213  	assert.Equal(t, values1, v)
   214  
   215  	v, err = rc.FetchBatch(keys2, 2*time.Second, genBatchDataFunc(values2, 200))
   216  	assert.Nil(t, err)
   217  	assert.True(t, time.Since(began) > time.Duration(150)*time.Millisecond)
   218  	for i := 40; i < 60; i++ {
   219  		assert.Equal(t, keys2[i-40], keys1[i])
   220  		assert.Equal(t, values1[i], v[i-40])
   221  	}
   222  	for i := 60; i < n; i++ {
   223  		assert.Equal(t, values2[i-40], v[i-40])
   224  	}
   225  
   226  	time.Sleep(time.Second)
   227  	v, err = rc.FetchBatch(keys2, 2*time.Second, genBatchDataFunc(values2, 100))
   228  	assert.Nil(t, err)
   229  	assert.Nil(t, err)
   230  	assert.Equal(t, values2, v)
   231  }
   232  
   233  func TestStrongErrorFetchBatch(t *testing.T) {
   234  	rc := NewClient(rdb, NewDefaultOptions())
   235  	rc.Options.StrongConsistency = true
   236  
   237  	clearCache()
   238  	began := time.Now()
   239  
   240  	n := 100
   241  	idxs := genIdxs(n)
   242  	keys := genKeys(idxs)
   243  
   244  	fetchError := errors.New("fetch error")
   245  	getFn := func(idxs []int) (map[int]string, error) {
   246  		return nil, fetchError
   247  	}
   248  	_, err := rc.FetchBatch(keys, 60*time.Second, getFn)
   249  	assert.Error(t, err)
   250  	fetchError = nil
   251  	_, err = rc.FetchBatch(keys, 60*time.Second, getFn)
   252  	assert.Nil(t, err)
   253  	assert.True(t, time.Since(began) < time.Duration(150)*time.Millisecond)
   254  }