github.com/Jeffail/benthos/v3@v3.65.0/lib/test/integration/redis_test.go (about)

     1  package integration
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"testing"
     7  	"time"
     8  
     9  	"github.com/Jeffail/benthos/v3/internal/integration"
    10  	"github.com/Jeffail/benthos/v3/lib/log"
    11  	"github.com/Jeffail/benthos/v3/lib/metrics"
    12  	"github.com/Jeffail/benthos/v3/lib/output/writer"
    13  	"github.com/go-redis/redis/v7"
    14  	"github.com/ory/dockertest/v3"
    15  	"github.com/stretchr/testify/assert"
    16  	"github.com/stretchr/testify/require"
    17  )
    18  
    19  var _ = registerIntegrationTest("redis", func(t *testing.T) {
    20  	t.Parallel()
    21  
    22  	pool, err := dockertest.NewPool("")
    23  	require.NoError(t, err)
    24  
    25  	pool.MaxWait = time.Second * 30
    26  	resource, err := pool.Run("redis", "latest", nil)
    27  	require.NoError(t, err)
    28  	t.Cleanup(func() {
    29  		assert.NoError(t, pool.Purge(resource))
    30  	})
    31  
    32  	resource.Expire(900)
    33  	require.NoError(t, pool.Retry(func() error {
    34  		conf := writer.NewRedisStreamsConfig()
    35  		conf.URL = fmt.Sprintf("tcp://localhost:%v", resource.GetPort("6379/tcp"))
    36  
    37  		r, cErr := writer.NewRedisStreams(conf, log.Noop(), metrics.Noop())
    38  		if cErr != nil {
    39  			return cErr
    40  		}
    41  		cErr = r.Connect()
    42  
    43  		r.CloseAsync()
    44  		return cErr
    45  	}))
    46  
    47  	// STREAMS
    48  	t.Run("streams", func(t *testing.T) {
    49  		t.Parallel()
    50  		template := `
    51  output:
    52    redis_streams:
    53      url: tcp://localhost:$PORT
    54      stream: stream-$ID
    55      body_key: body
    56      max_length: 0
    57      max_in_flight: $MAX_IN_FLIGHT
    58      metadata:
    59        exclude_prefixes: [ $OUTPUT_META_EXCLUDE_PREFIX ]
    60      batching:
    61        count: $OUTPUT_BATCH_COUNT
    62  
    63  input:
    64    redis_streams:
    65      url: tcp://localhost:$PORT
    66      body_key: body
    67      streams: [ stream-$ID ]
    68      limit: 10
    69      client_id: client-input-$ID
    70      consumer_group: group-$ID
    71  `
    72  		suite := integration.StreamTests(
    73  			integration.StreamTestOpenClose(),
    74  			integration.StreamTestMetadata(),
    75  			integration.StreamTestMetadataFilter(),
    76  			integration.StreamTestSendBatch(10),
    77  			integration.StreamTestSendBatches(20, 100, 1),
    78  			integration.StreamTestStreamSequential(1000),
    79  			integration.StreamTestStreamParallel(1000),
    80  			integration.StreamTestStreamParallelLossy(1000),
    81  			integration.StreamTestStreamParallelLossyThroughReconnect(100),
    82  			integration.StreamTestSendBatchCount(10),
    83  		)
    84  		suite.Run(
    85  			t, template,
    86  			integration.StreamTestOptSleepAfterInput(100*time.Millisecond),
    87  			integration.StreamTestOptSleepAfterOutput(100*time.Millisecond),
    88  			integration.StreamTestOptPort(resource.GetPort("6379/tcp")),
    89  		)
    90  		t.Run("with max in flight", func(t *testing.T) {
    91  			t.Parallel()
    92  			suite.Run(
    93  				t, template,
    94  				integration.StreamTestOptSleepAfterInput(100*time.Millisecond),
    95  				integration.StreamTestOptSleepAfterOutput(100*time.Millisecond),
    96  				integration.StreamTestOptPort(resource.GetPort("6379/tcp")),
    97  				integration.StreamTestOptMaxInFlight(10),
    98  			)
    99  		})
   100  	})
   101  
   102  	t.Run("pubsub", func(t *testing.T) {
   103  		t.Parallel()
   104  		template := `
   105  output:
   106    redis_pubsub:
   107      url: tcp://localhost:$PORT
   108      channel: channel-$ID
   109      max_in_flight: $MAX_IN_FLIGHT
   110      batching:
   111        count: $OUTPUT_BATCH_COUNT
   112  
   113  input:
   114    redis_pubsub:
   115      url: tcp://localhost:$PORT
   116      channels: [ channel-$ID ]
   117  `
   118  		suite := integration.StreamTests(
   119  			integration.StreamTestOpenClose(),
   120  			integration.StreamTestSendBatch(10),
   121  			integration.StreamTestSendBatches(20, 100, 1),
   122  			integration.StreamTestStreamSequential(100),
   123  			integration.StreamTestStreamParallel(100),
   124  			integration.StreamTestStreamParallelLossy(100),
   125  			integration.StreamTestSendBatchCount(10),
   126  		)
   127  		suite.Run(
   128  			t, template,
   129  			integration.StreamTestOptSleepAfterInput(500*time.Millisecond),
   130  			integration.StreamTestOptSleepAfterOutput(500*time.Millisecond),
   131  			integration.StreamTestOptPort(resource.GetPort("6379/tcp")),
   132  		)
   133  		t.Run("with max in flight", func(t *testing.T) {
   134  			t.Parallel()
   135  			suite.Run(
   136  				t, template,
   137  				integration.StreamTestOptSleepAfterInput(500*time.Millisecond),
   138  				integration.StreamTestOptSleepAfterOutput(500*time.Millisecond),
   139  				integration.StreamTestOptPort(resource.GetPort("6379/tcp")),
   140  				integration.StreamTestOptMaxInFlight(10),
   141  			)
   142  		})
   143  	})
   144  
   145  	t.Run("list", func(t *testing.T) {
   146  		t.Parallel()
   147  		template := `
   148  output:
   149    redis_list:
   150      url: tcp://localhost:$PORT
   151      key: key-$ID
   152      max_in_flight: $MAX_IN_FLIGHT
   153      batching:
   154        count: $OUTPUT_BATCH_COUNT
   155  
   156  input:
   157    redis_list:
   158      url: tcp://localhost:$PORT
   159      key: key-$ID
   160  `
   161  		suite := integration.StreamTests(
   162  			integration.StreamTestOpenClose(),
   163  			integration.StreamTestSendBatch(10),
   164  			integration.StreamTestSendBatches(20, 100, 1),
   165  			integration.StreamTestStreamSequential(1000),
   166  			integration.StreamTestStreamParallel(1000),
   167  			integration.StreamTestStreamParallelLossy(1000),
   168  			integration.StreamTestSendBatchCount(10),
   169  		)
   170  		suite.Run(
   171  			t, template,
   172  			integration.StreamTestOptSleepAfterInput(100*time.Millisecond),
   173  			integration.StreamTestOptSleepAfterOutput(100*time.Millisecond),
   174  			integration.StreamTestOptPort(resource.GetPort("6379/tcp")),
   175  		)
   176  		t.Run("with max in flight", func(t *testing.T) {
   177  			t.Parallel()
   178  			suite.Run(
   179  				t, template,
   180  				integration.StreamTestOptSleepAfterInput(100*time.Millisecond),
   181  				integration.StreamTestOptSleepAfterOutput(100*time.Millisecond),
   182  				integration.StreamTestOptPort(resource.GetPort("6379/tcp")),
   183  				integration.StreamTestOptMaxInFlight(10),
   184  			)
   185  		})
   186  	})
   187  
   188  	// HASH
   189  	t.Run("hash", func(t *testing.T) {
   190  		t.Parallel()
   191  		template := `
   192  output:
   193    redis_hash:
   194      url: tcp://localhost:$PORT
   195      key: $ID-${! json("id") }
   196      fields:
   197        content: ${! content() }
   198  `
   199  		hashGetFn := func(ctx context.Context, testID string, id string) (string, []string, error) {
   200  			client := redis.NewClient(&redis.Options{
   201  				Addr:    fmt.Sprintf("localhost:%v", resource.GetPort("6379/tcp")),
   202  				Network: "tcp",
   203  			})
   204  			key := testID + "-" + id
   205  			res, err := client.HGet(key, "content").Result()
   206  			if err != nil {
   207  				return "", nil, err
   208  			}
   209  			return res, nil, nil
   210  		}
   211  		suite := integration.StreamTests(
   212  			integration.StreamTestOutputOnlySendSequential(10, hashGetFn),
   213  			integration.StreamTestOutputOnlySendBatch(10, hashGetFn),
   214  			integration.StreamTestOutputOnlyOverride(hashGetFn),
   215  		)
   216  		suite.Run(
   217  			t, template,
   218  			integration.StreamTestOptSleepAfterInput(100*time.Millisecond),
   219  			integration.StreamTestOptSleepAfterOutput(100*time.Millisecond),
   220  			integration.StreamTestOptPort(resource.GetPort("6379/tcp")),
   221  		)
   222  	})
   223  })
   224  
   225  var _ = registerIntegrationBench("redis", func(b *testing.B) {
   226  	pool, err := dockertest.NewPool("")
   227  	require.NoError(b, err)
   228  
   229  	pool.MaxWait = time.Second * 30
   230  	resource, err := pool.Run("redis", "latest", nil)
   231  	require.NoError(b, err)
   232  	b.Cleanup(func() {
   233  		assert.NoError(b, pool.Purge(resource))
   234  	})
   235  
   236  	resource.Expire(900)
   237  	require.NoError(b, pool.Retry(func() error {
   238  		conf := writer.NewRedisStreamsConfig()
   239  		conf.URL = fmt.Sprintf("tcp://localhost:%v", resource.GetPort("6379/tcp"))
   240  
   241  		r, cErr := writer.NewRedisStreams(conf, log.Noop(), metrics.Noop())
   242  		if cErr != nil {
   243  			return cErr
   244  		}
   245  		cErr = r.Connect()
   246  
   247  		r.CloseAsync()
   248  		return cErr
   249  	}))
   250  
   251  	// STREAMS
   252  	b.Run("streams", func(b *testing.B) {
   253  		template := `
   254  output:
   255    redis_streams:
   256      url: tcp://localhost:$PORT
   257      stream: stream-$ID
   258      body_key: body
   259      max_length: 0
   260      max_in_flight: $MAX_IN_FLIGHT
   261      metadata:
   262        exclude_prefixes: [ $OUTPUT_META_EXCLUDE_PREFIX ]
   263  
   264  input:
   265    redis_streams:
   266      url: tcp://localhost:$PORT
   267      body_key: body
   268      streams: [ stream-$ID ]
   269      limit: 10
   270      client_id: client-input-$ID
   271      consumer_group: group-$ID
   272  `
   273  		suite := integration.StreamBenchs(
   274  			integration.StreamBenchSend(20, 1),
   275  			integration.StreamBenchSend(10, 1),
   276  			integration.StreamBenchSend(1, 1),
   277  			integration.StreamBenchWrite(20),
   278  			integration.StreamBenchWrite(10),
   279  			integration.StreamBenchWrite(1),
   280  		)
   281  		suite.Run(
   282  			b, template,
   283  			integration.StreamTestOptSleepAfterInput(100*time.Millisecond),
   284  			integration.StreamTestOptSleepAfterOutput(100*time.Millisecond),
   285  			integration.StreamTestOptPort(resource.GetPort("6379/tcp")),
   286  		)
   287  	})
   288  
   289  	b.Run("pubsub", func(b *testing.B) {
   290  		template := `
   291  output:
   292    redis_pubsub:
   293      url: tcp://localhost:$PORT
   294      channel: channel-$ID
   295      max_in_flight: $MAX_IN_FLIGHT
   296  
   297  input:
   298    redis_pubsub:
   299      url: tcp://localhost:$PORT
   300      channels: [ channel-$ID ]
   301  `
   302  		suite := integration.StreamBenchs(
   303  			integration.StreamBenchSend(20, 1),
   304  			integration.StreamBenchSend(10, 1),
   305  			integration.StreamBenchSend(1, 1),
   306  			integration.StreamBenchWrite(20),
   307  			integration.StreamBenchWrite(10),
   308  			integration.StreamBenchWrite(1),
   309  		)
   310  		suite.Run(
   311  			b, template,
   312  			integration.StreamTestOptSleepAfterInput(500*time.Millisecond),
   313  			integration.StreamTestOptSleepAfterOutput(500*time.Millisecond),
   314  			integration.StreamTestOptPort(resource.GetPort("6379/tcp")),
   315  		)
   316  	})
   317  
   318  	b.Run("list", func(b *testing.B) {
   319  		template := `
   320  output:
   321    redis_list:
   322      url: tcp://localhost:$PORT
   323      key: key-$ID
   324      max_in_flight: $MAX_IN_FLIGHT
   325  
   326  input:
   327    redis_list:
   328      url: tcp://localhost:$PORT
   329      key: key-$ID
   330  `
   331  		suite := integration.StreamBenchs(
   332  			integration.StreamBenchSend(20, 1),
   333  			integration.StreamBenchSend(10, 1),
   334  			integration.StreamBenchSend(1, 1),
   335  			integration.StreamBenchWrite(20),
   336  			integration.StreamBenchWrite(10),
   337  			integration.StreamBenchWrite(1),
   338  		)
   339  		suite.Run(
   340  			b, template,
   341  			integration.StreamTestOptSleepAfterInput(100*time.Millisecond),
   342  			integration.StreamTestOptSleepAfterOutput(100*time.Millisecond),
   343  			integration.StreamTestOptPort(resource.GetPort("6379/tcp")),
   344  		)
   345  	})
   346  })