github.com/Jeffail/benthos/v3@v3.65.0/lib/output/writer/cache_test.go (about)

     1  package writer
     2  
     3  import (
     4  	"errors"
     5  	"net/http"
     6  	"testing"
     7  	"time"
     8  
     9  	"github.com/Jeffail/benthos/v3/lib/log"
    10  	"github.com/Jeffail/benthos/v3/lib/message"
    11  	"github.com/Jeffail/benthos/v3/lib/metrics"
    12  	"github.com/Jeffail/benthos/v3/lib/types"
    13  	"github.com/stretchr/testify/assert"
    14  	"github.com/stretchr/testify/require"
    15  )
    16  
    17  func TestCacheSingle(t *testing.T) {
    18  	c := &basicCache{
    19  		values: map[string]string{},
    20  	}
    21  
    22  	mgr := &fakeMgr{
    23  		caches: map[string]types.Cache{
    24  			"foocache": c,
    25  		},
    26  	}
    27  
    28  	conf := NewCacheConfig()
    29  	conf.Key = `${!json("id")}`
    30  	conf.Target = "foocache"
    31  
    32  	w, err := NewCache(conf, mgr, log.Noop(), metrics.Noop())
    33  	require.NoError(t, err)
    34  
    35  	require.NoError(t, w.Write(message.New([][]byte{
    36  		[]byte(`{"id":"1","value":"first"}`),
    37  	})))
    38  
    39  	assert.Equal(t, map[string]string{
    40  		"1": `{"id":"1","value":"first"}`,
    41  	}, c.values)
    42  }
    43  
    44  func TestCacheBatch(t *testing.T) {
    45  	c := &basicCache{
    46  		values: map[string]string{},
    47  	}
    48  
    49  	mgr := &fakeMgr{
    50  		caches: map[string]types.Cache{
    51  			"foocache": c,
    52  		},
    53  	}
    54  
    55  	conf := NewCacheConfig()
    56  	conf.Key = `${!json("id")}`
    57  	conf.Target = "foocache"
    58  
    59  	w, err := NewCache(conf, mgr, log.Noop(), metrics.Noop())
    60  	require.NoError(t, err)
    61  
    62  	require.NoError(t, w.Write(message.New([][]byte{
    63  		[]byte(`{"id":"1","value":"first"}`),
    64  		[]byte(`{"id":"2","value":"second"}`),
    65  		[]byte(`{"id":"3","value":"third"}`),
    66  		[]byte(`{"id":"4","value":"fourth"}`),
    67  	})))
    68  
    69  	assert.Equal(t, map[string]string{
    70  		"1": `{"id":"1","value":"first"}`,
    71  		"2": `{"id":"2","value":"second"}`,
    72  		"3": `{"id":"3","value":"third"}`,
    73  		"4": `{"id":"4","value":"fourth"}`,
    74  	}, c.values)
    75  }
    76  
    77  func TestCacheSingleTTL(t *testing.T) {
    78  	c := &ttlCache{
    79  		values: map[string]ttlCacheItem{},
    80  	}
    81  
    82  	mgr := &fakeMgr{
    83  		caches: map[string]types.Cache{
    84  			"foocache": c,
    85  		},
    86  	}
    87  
    88  	conf := NewCacheConfig()
    89  	conf.Key = `${!json("id")}`
    90  	conf.Target = "foocache"
    91  	conf.TTL = "2s"
    92  
    93  	w, err := NewCache(conf, mgr, log.Noop(), metrics.Noop())
    94  	require.NoError(t, err)
    95  
    96  	require.NoError(t, w.Write(message.New([][]byte{
    97  		[]byte(`{"id":"1","value":"first"}`),
    98  	})))
    99  
   100  	twosec := time.Second * 2
   101  
   102  	assert.Equal(t, map[string]ttlCacheItem{
   103  		"1": {
   104  			value: `{"id":"1","value":"first"}`,
   105  			ttl:   &twosec,
   106  		},
   107  	}, c.values)
   108  }
   109  
   110  func TestCacheBatchTTL(t *testing.T) {
   111  	c := &ttlCache{
   112  		values: map[string]ttlCacheItem{},
   113  	}
   114  
   115  	mgr := &fakeMgr{
   116  		caches: map[string]types.Cache{
   117  			"foocache": c,
   118  		},
   119  	}
   120  
   121  	conf := NewCacheConfig()
   122  	conf.Key = `${!json("id")}`
   123  	conf.Target = "foocache"
   124  	conf.TTL = "2s"
   125  
   126  	w, err := NewCache(conf, mgr, log.Noop(), metrics.Noop())
   127  	require.NoError(t, err)
   128  
   129  	require.NoError(t, w.Write(message.New([][]byte{
   130  		[]byte(`{"id":"1","value":"first"}`),
   131  		[]byte(`{"id":"2","value":"second"}`),
   132  		[]byte(`{"id":"3","value":"third"}`),
   133  		[]byte(`{"id":"4","value":"fourth"}`),
   134  	})))
   135  
   136  	twosec := time.Second * 2
   137  
   138  	assert.Equal(t, map[string]ttlCacheItem{
   139  		"1": {
   140  			value: `{"id":"1","value":"first"}`,
   141  			ttl:   &twosec,
   142  		},
   143  		"2": {
   144  			value: `{"id":"2","value":"second"}`,
   145  			ttl:   &twosec,
   146  		},
   147  		"3": {
   148  			value: `{"id":"3","value":"third"}`,
   149  			ttl:   &twosec,
   150  		},
   151  		"4": {
   152  			value: `{"id":"4","value":"fourth"}`,
   153  			ttl:   &twosec,
   154  		},
   155  	}, c.values)
   156  }
   157  
   158  //------------------------------------------------------------------------------
   159  
   160  type fakeMgr struct {
   161  	caches     map[string]types.Cache
   162  	ratelimits map[string]types.RateLimit
   163  }
   164  
   165  func (f *fakeMgr) RegisterEndpoint(path, desc string, h http.HandlerFunc) {
   166  }
   167  func (f *fakeMgr) GetCache(name string) (types.Cache, error) {
   168  	if c, exists := f.caches[name]; exists {
   169  		return c, nil
   170  	}
   171  	return nil, types.ErrCacheNotFound
   172  }
   173  func (f *fakeMgr) GetCondition(name string) (types.Condition, error) {
   174  	return nil, types.ErrConditionNotFound
   175  }
   176  func (f *fakeMgr) GetRateLimit(name string) (types.RateLimit, error) {
   177  	if r, exists := f.ratelimits[name]; exists {
   178  		return r, nil
   179  	}
   180  	return nil, types.ErrRateLimitNotFound
   181  }
   182  func (f *fakeMgr) GetPlugin(name string) (interface{}, error) {
   183  	return nil, types.ErrPluginNotFound
   184  }
   185  func (f *fakeMgr) GetPipe(name string) (<-chan types.Transaction, error) {
   186  	return nil, types.ErrPipeNotFound
   187  }
   188  func (f *fakeMgr) SetPipe(name string, prod <-chan types.Transaction)   {}
   189  func (f *fakeMgr) UnsetPipe(name string, prod <-chan types.Transaction) {}
   190  
   191  //------------------------------------------------------------------------------
   192  
   193  type basicCache struct {
   194  	values map[string]string
   195  }
   196  
   197  func (b *basicCache) Get(key string) ([]byte, error) {
   198  	return nil, errors.New("not implemented")
   199  }
   200  
   201  func (b *basicCache) Set(key string, value []byte) error {
   202  	b.values[key] = string(value)
   203  	return nil
   204  }
   205  
   206  func (b *basicCache) SetMulti(items map[string][]byte) error {
   207  	for k, v := range items {
   208  		b.values[k] = string(v)
   209  	}
   210  	return nil
   211  }
   212  
   213  func (b *basicCache) Add(key string, value []byte) error {
   214  	return errors.New("not implemented")
   215  }
   216  
   217  func (b *basicCache) Delete(key string) error {
   218  	return errors.New("not implemented")
   219  }
   220  
   221  func (b *basicCache) CloseAsync() {}
   222  
   223  func (b *basicCache) WaitForClose(time.Duration) error {
   224  	return nil
   225  }
   226  
   227  //------------------------------------------------------------------------------
   228  
   229  type ttlCacheItem struct {
   230  	value string
   231  	ttl   *time.Duration
   232  }
   233  
   234  type ttlCache struct {
   235  	values map[string]ttlCacheItem
   236  }
   237  
   238  func (t *ttlCache) Get(key string) ([]byte, error) {
   239  	return nil, errors.New("not implemented")
   240  }
   241  
   242  func (t *ttlCache) Set(key string, value []byte) error {
   243  	t.values[key] = ttlCacheItem{
   244  		value: string(value),
   245  	}
   246  	return nil
   247  }
   248  
   249  func (t *ttlCache) SetWithTTL(key string, value []byte, ttl *time.Duration) error {
   250  	t.values[key] = ttlCacheItem{
   251  		value: string(value),
   252  		ttl:   ttl,
   253  	}
   254  	return nil
   255  }
   256  
   257  func (t *ttlCache) SetMulti(items map[string][]byte) error {
   258  	for k, v := range items {
   259  		t.values[k] = ttlCacheItem{
   260  			value: string(v),
   261  		}
   262  	}
   263  	return nil
   264  }
   265  
   266  func (t *ttlCache) SetMultiWithTTL(items map[string]types.CacheTTLItem) error {
   267  	for k, v := range items {
   268  		t.values[k] = ttlCacheItem{
   269  			value: string(v.Value),
   270  			ttl:   v.TTL,
   271  		}
   272  	}
   273  	return nil
   274  }
   275  
   276  func (t *ttlCache) Add(key string, value []byte) error {
   277  	return errors.New("not implemented")
   278  }
   279  
   280  func (t *ttlCache) AddWithTTL(key string, value []byte, ttl *time.Duration) error {
   281  	return errors.New("not implemented")
   282  }
   283  
   284  func (t *ttlCache) Delete(key string) error {
   285  	return errors.New("not implemented")
   286  }
   287  
   288  func (t *ttlCache) CloseAsync() {}
   289  
   290  func (t *ttlCache) WaitForClose(time.Duration) error {
   291  	return nil
   292  }