├── docs ├── index.md ├── css │ └── extra.css └── static │ └── favicon.ico ├── src ├── main │ ├── resources │ │ └── META-INF │ │ │ ├── services │ │ │ ├── io.lettuce.core.json.JsonParser │ │ │ └── javax.enterprise.inject.spi.Extension │ │ │ └── native-image │ │ │ └── io.lettuce │ │ │ └── lettuce-core │ │ │ └── native-image.properties │ ├── java │ │ └── io │ │ │ └── lettuce │ │ │ └── core │ │ │ ├── api │ │ │ ├── package-info.java │ │ │ ├── push │ │ │ │ ├── package-info.java │ │ │ │ └── PushListener.java │ │ │ ├── sync │ │ │ │ └── package-info.java │ │ │ ├── async │ │ │ │ └── package-info.java │ │ │ ├── reactive │ │ │ │ └── package-info.java │ │ │ └── AsyncCloseable.java │ │ │ ├── pubsub │ │ │ ├── package-info.java │ │ │ ├── api │ │ │ │ ├── async │ │ │ │ │ └── package-info.java │ │ │ │ ├── sync │ │ │ │ │ └── package-info.java │ │ │ │ └── reactive │ │ │ │ │ ├── package-info.java │ │ │ │ │ └── ChannelMessage.java │ │ │ ├── PubSubCommandArgs.java │ │ │ └── PubSubMessage.java │ │ │ ├── cluster │ │ │ ├── event │ │ │ │ ├── package-info.java │ │ │ │ ├── AskRedirectionEvent.java │ │ │ │ ├── MovedRedirectionEvent.java │ │ │ │ ├── TopologyRefreshEvent.java │ │ │ │ ├── JfrAskRedirectionEvent.java │ │ │ │ ├── JfrMovedRedirectionEvent.java │ │ │ │ ├── RedirectionEventSupport.java │ │ │ │ └── JfrTopologyRefreshEvent.java │ │ │ ├── api │ │ │ │ ├── package-info.java │ │ │ │ ├── sync │ │ │ │ │ ├── package-info.java │ │ │ │ │ ├── NodeSelection.java │ │ │ │ │ └── NodeSelectionCommands.java │ │ │ │ ├── async │ │ │ │ │ ├── package-info.java │ │ │ │ │ └── AsyncNodeSelection.java │ │ │ │ ├── push │ │ │ │ │ ├── package-info.java │ │ │ │ │ └── RedisClusterPushListener.java │ │ │ │ └── reactive │ │ │ │ │ ├── package-info.java │ │ │ │ │ └── ReactiveExecutions.java │ │ │ ├── pubsub │ │ │ │ ├── package-info.java │ │ │ │ └── api │ │ │ │ │ ├── sync │ │ │ │ │ ├── package-info.java │ │ │ │ │ └── PubSubNodeSelection.java │ │ │ │ │ ├── async │ │ │ │ │ ├── package-info.java │ │ │ │ │ └── PubSubAsyncNodeSelection.java │ │ │ │ │ └── reactive │ │ │ │ │ ├── package-info.java │ │ │ │ │ └── PubSubReactiveNodeSelection.java │ │ │ ├── topology │ │ │ │ ├── package-info.java │ │ │ │ └── RedisClusterNodeSnapshot.java │ │ │ ├── models │ │ │ │ ├── slots │ │ │ │ │ └── package-info.java │ │ │ │ └── partitions │ │ │ │ │ └── package-info.java │ │ │ ├── package-info.java │ │ │ ├── UnknownPartitionException.java │ │ │ ├── ReconnectEventListener.java │ │ │ ├── PartitionSelectorException.java │ │ │ └── ClusterPushHandler.java │ │ │ ├── event │ │ │ ├── package-info.java │ │ │ ├── cluster │ │ │ │ └── package-info.java │ │ │ ├── command │ │ │ │ └── package-info.java │ │ │ ├── metrics │ │ │ │ ├── package-info.java │ │ │ │ └── MetricEventPublisher.java │ │ │ ├── connection │ │ │ │ ├── package-info.java │ │ │ │ ├── ConnectionEvent.java │ │ │ │ ├── AuthenticationEvent.java │ │ │ │ ├── ConnectedEvent.java │ │ │ │ ├── DisconnectedEvent.java │ │ │ │ ├── ConnectEvent.java │ │ │ │ ├── ConnectionDeactivatedEvent.java │ │ │ │ ├── ConnectionCreatedEvent.java │ │ │ │ ├── ConnectionActivatedEvent.java │ │ │ │ ├── JfrConnectionCreatedEvent.java │ │ │ │ ├── ReauthenticationEvent.java │ │ │ │ ├── JfrConnectEvent.java │ │ │ │ ├── JfrConnectedEvent.java │ │ │ │ ├── JfrDisconnectedEvent.java │ │ │ │ ├── JfrConnectionActivatedEvent.java │ │ │ │ └── JfrConnectionDeactivatedEvent.java │ │ │ ├── jfr │ │ │ │ ├── package-info.java │ │ │ │ └── NoOpEventRecorder.java │ │ │ ├── Event.java │ │ │ ├── EventPublisherOptions.java │ │ │ └── EventBus.java │ │ │ ├── json │ │ │ ├── package-info.java │ │ │ ├── RedisJsonException.java │ │ │ └── JsonType.java │ │ │ ├── metrics │ │ │ └── package-info.java │ │ │ ├── codec │ │ │ ├── package-info.java │ │ │ └── ByteBufferInputStream.java │ │ │ ├── protocol │ │ │ ├── package-info.java │ │ │ ├── RedisProtocolException.java │ │ │ ├── DecoratedCommand.java │ │ │ ├── HasQueuedCommands.java │ │ │ ├── ConnectionIntent.java │ │ │ ├── ProtocolVersion.java │ │ │ ├── RebindState.java │ │ │ ├── ReconnectionListener.java │ │ │ ├── TransactionalCommand.java │ │ │ ├── ConnectionInitializer.java │ │ │ ├── ProtocolKeyword.java │ │ │ ├── ConnectionFacade.java │ │ │ ├── ActivationCommand.java │ │ │ └── PushHandler.java │ │ │ ├── sentinel │ │ │ ├── package-info.java │ │ │ └── api │ │ │ │ ├── package-info.java │ │ │ │ ├── async │ │ │ │ └── package-info.java │ │ │ │ ├── sync │ │ │ │ └── package-info.java │ │ │ │ └── reactive │ │ │ │ └── package-info.java │ │ │ ├── dynamic │ │ │ ├── intercept │ │ │ │ ├── package-info.java │ │ │ │ ├── InvocationTargetProvider.java │ │ │ │ └── MethodInterceptor.java │ │ │ ├── batch │ │ │ │ ├── package-info.java │ │ │ │ └── BatchExecutor.java │ │ │ ├── parameter │ │ │ │ └── package-info.java │ │ │ ├── support │ │ │ │ └── package-info.java │ │ │ ├── codec │ │ │ │ ├── package-info.java │ │ │ │ └── RedisCodecResolver.java │ │ │ ├── domain │ │ │ │ └── package-info.java │ │ │ ├── output │ │ │ │ ├── package-info.java │ │ │ │ └── CommandOutputFactory.java │ │ │ ├── annotation │ │ │ │ ├── package-info.java │ │ │ │ ├── Key.java │ │ │ │ ├── Value.java │ │ │ │ └── Param.java │ │ │ ├── segment │ │ │ │ ├── package-info.java │ │ │ │ └── CommandSegmentFactory.java │ │ │ ├── package-info.java │ │ │ ├── Commands.java │ │ │ ├── CommandFactoryResolver.java │ │ │ ├── CommandMethodSyntaxException.java │ │ │ ├── ExecutableCommand.java │ │ │ ├── CommandFactory.java │ │ │ ├── ExecutableCommandLookupStrategy.java │ │ │ ├── CommandMethodVerifier.java │ │ │ ├── BatchTasks.java │ │ │ ├── CommandCreationException.java │ │ │ └── RedisCommandsMetadata.java │ │ │ ├── resource │ │ │ ├── package-info.java │ │ │ ├── ConstantDelay.java │ │ │ ├── DefaultThreadFactoryProvider.java │ │ │ ├── DefaultNettyCustomizer.java │ │ │ ├── ThreadFactoryProvider.java │ │ │ └── DnsResolvers.java │ │ │ ├── models │ │ │ ├── role │ │ │ │ ├── package-info.java │ │ │ │ ├── RedisNodeDescription.java │ │ │ │ └── RedisMasterInstance.java │ │ │ ├── command │ │ │ │ └── package-info.java │ │ │ └── stream │ │ │ │ └── package-info.java │ │ │ ├── output │ │ │ ├── package-info.java │ │ │ ├── StreamingChannel.java │ │ │ ├── ArrayOutput.java │ │ │ ├── ValueStreamingChannel.java │ │ │ ├── KeyStreamingChannel.java │ │ │ ├── OutputFactory.java │ │ │ ├── ScoredValueStreamingChannel.java │ │ │ ├── KeyValueStreamingChannel.java │ │ │ ├── KeyScanOutput.java │ │ │ ├── ValueScanOutput.java │ │ │ ├── KeyStreamingOutput.java │ │ │ ├── ComplexDataParser.java │ │ │ ├── ValueStreamingOutput.java │ │ │ ├── ValueScanStreamingOutput.java │ │ │ ├── EncodedComplexOutput.java │ │ │ ├── KeyScanStreamingOutput.java │ │ │ ├── SocketAddressOutput.java │ │ │ └── MapScanOutput.java │ │ │ ├── tracing │ │ │ ├── package-info.java │ │ │ ├── TracerProvider.java │ │ │ ├── TraceContext.java │ │ │ ├── TraceContextProvider.java │ │ │ ├── LettuceObservationConvention.java │ │ │ └── SocketAddressEndpoint.java │ │ │ ├── package-info.java │ │ │ ├── internal │ │ │ ├── package-info.java │ │ │ └── AsyncCloseable.java │ │ │ ├── support │ │ │ ├── package-info.java │ │ │ └── caching │ │ │ │ └── MapCacheAccessor.java │ │ │ ├── search │ │ │ └── package-info.java │ │ │ ├── KeyScanCursor.java │ │ │ ├── StreamScanCursor.java │ │ │ ├── SslVerifyMode.java │ │ │ ├── ValueScanCursor.java │ │ │ ├── MapScanCursor.java │ │ │ ├── ScoredValueScanCursor.java │ │ │ ├── UnblockType.java │ │ │ ├── ConnectionId.java │ │ │ ├── EpollProvider.java │ │ │ ├── masterreplica │ │ │ ├── MasterReplicaConnector.java │ │ │ ├── NoOpPushHandler.java │ │ │ ├── Timeout.java │ │ │ ├── package-info.java │ │ │ ├── SentinelTopologyRefreshEvent.java │ │ │ ├── MasterReplicaTopologyChangedEvent.java │ │ │ ├── RedisClientNodeConnectionFactory.java │ │ │ ├── NodeConnectionFactory.java │ │ │ └── JfrSentinelTopologyRefreshEvent.java │ │ │ ├── KqueueProvider.java │ │ │ ├── ConnectionPoint.java │ │ │ ├── vector │ │ │ └── VSimScoreAttribs.java │ │ │ ├── CloseEvents.java │ │ │ ├── RedisConnectionStateAdapter.java │ │ │ ├── masterslave │ │ │ └── package-info.java │ │ │ ├── RedisBusyException.java │ │ │ ├── RedisLoadingException.java │ │ │ ├── OrderingReadFromAccessor.java │ │ │ ├── RedisNoScriptException.java │ │ │ └── RedisCommandTimeoutException.java │ └── kotlin │ │ └── io │ │ └── lettuce │ │ └── core │ │ ├── api │ │ └── StatefulRedisConnectionExtensions.kt │ │ ├── cluster │ │ └── api │ │ │ └── StatefulRedisClusterConnectionExtensions.kt │ │ └── sentinel │ │ └── api │ │ └── StatefulRedisSentinelConnectionExtensions.kt ├── test │ ├── resources │ │ ├── docker-env │ │ │ ├── .env │ │ │ ├── .env.v8.0 │ │ │ ├── .env.v7.2 │ │ │ ├── .env.v7.4 │ │ │ ├── .env.v8.2 │ │ │ ├── ssl-test-cluster │ │ │ │ └── config │ │ │ │ │ ├── node-7479 │ │ │ │ │ ├── redis.conf │ │ │ │ │ └── nodes.conf │ │ │ │ │ ├── node-7480 │ │ │ │ │ ├── redis.conf │ │ │ │ │ └── nodes.conf │ │ │ │ │ └── node-7481 │ │ │ │ │ ├── redis.conf │ │ │ │ │ └── nodes.conf │ │ │ ├── test-cluster │ │ │ │ └── config │ │ │ │ │ ├── node-7379 │ │ │ │ │ ├── redis.conf │ │ │ │ │ └── nodes.conf │ │ │ │ │ ├── node-7380 │ │ │ │ │ ├── redis.conf │ │ │ │ │ └── nodes.conf │ │ │ │ │ ├── node-7381 │ │ │ │ │ ├── redis.conf │ │ │ │ │ └── nodes.conf │ │ │ │ │ ├── node-7382 │ │ │ │ │ ├── redis.conf │ │ │ │ │ └── nodes.conf │ │ │ │ │ ├── node-7383 │ │ │ │ │ └── redis.conf │ │ │ │ │ ├── node-7384 │ │ │ │ │ └── redis.conf │ │ │ │ │ ├── node-7582 │ │ │ │ │ ├── redis.conf │ │ │ │ │ └── nodes.conf │ │ │ │ │ └── node-7385 │ │ │ │ │ └── redis.conf │ │ │ ├── redis-standalone-5-client-cert │ │ │ │ └── config │ │ │ │ │ └── node-6478 │ │ │ │ │ └── redis.conf │ │ │ ├── redis-standalone-1 │ │ │ │ └── config │ │ │ │ │ ├── node-6486 │ │ │ │ │ └── redis.conf │ │ │ │ │ └── node-6479 │ │ │ │ │ └── redis.conf │ │ │ ├── redis-standalone-2 │ │ │ │ └── config │ │ │ │ │ └── node-6480 │ │ │ │ │ └── redis.conf │ │ │ ├── redis-standalone-3 │ │ │ │ └── config │ │ │ │ │ └── node-6481 │ │ │ │ │ └── redis.conf │ │ │ ├── redis-standalone-4 │ │ │ │ └── config │ │ │ │ │ ├── node-6484 │ │ │ │ │ └── redis.conf │ │ │ │ │ └── node-sentinel-26381 │ │ │ │ │ └── redis.conf │ │ │ ├── redis-standalone-0 │ │ │ │ └── config │ │ │ │ │ └── node-6478 │ │ │ │ │ └── redis.conf │ │ │ └── redis-standalone-sentinel-controlled │ │ │ │ └── config │ │ │ │ ├── node-6482 │ │ │ │ └── redis.conf │ │ │ │ ├── node-6483 │ │ │ │ └── redis.conf │ │ │ │ ├── node-sentinel-26380 │ │ │ │ └── redis.conf │ │ │ │ └── node-sentinel-26379 │ │ │ │ └── redis.conf │ │ ├── META-INF │ │ │ └── beans.xml │ │ ├── .env.entraid │ │ ├── io │ │ │ └── lettuce │ │ │ │ └── examples │ │ │ │ └── SpringTest-context.xml │ │ └── spring-test.xml │ ├── java │ │ └── io │ │ │ └── lettuce │ │ │ ├── category │ │ │ └── SlowTests.java │ │ │ ├── core │ │ │ ├── support │ │ │ │ └── PersonDB.java │ │ │ ├── RedisClientListenerIntegrationTests.java │ │ │ ├── sentinel │ │ │ │ └── SentinelTestSettings.java │ │ │ ├── ScoredValueStreamingAdapter.java │ │ │ ├── commands │ │ │ │ ├── BitStringCodec.java │ │ │ │ ├── transactional │ │ │ │ │ ├── HLLTxCommandIntegrationTests.java │ │ │ │ │ ├── SetTxCommandIntegrationTests.java │ │ │ │ │ ├── HashTxCommandIntegrationTests.java │ │ │ │ │ ├── ListTxCommandIntegrationTests.java │ │ │ │ │ ├── SortTxCommandIntegrationTests.java │ │ │ │ │ ├── StringTxCommandIntegrationTests.java │ │ │ │ │ ├── SortedSetTxCommandIntegrationTests.java │ │ │ │ │ ├── BitTxCommandIntegrationTests.java │ │ │ │ │ ├── KeyTxCommandIntegrationTests.java │ │ │ │ │ └── StreamTxCommandIntegrationTests.java │ │ │ │ └── reactive │ │ │ │ │ ├── HLLReactiveCommandIntegrationTests.java │ │ │ │ │ ├── KeyReactiveCommandIntegrationTests.java │ │ │ │ │ ├── SetReactiveCommandIntegrationTests.java │ │ │ │ │ ├── ListReactiveCommandIntegrationTests.java │ │ │ │ │ ├── SortReactiveCommandIntegrationTests.java │ │ │ │ │ ├── StreamReactiveCommandIntegrationTests.java │ │ │ │ │ ├── NumericReactiveCommandIntegrationTests.java │ │ │ │ │ ├── FunctionReactiveCommandIntegrationTests.java │ │ │ │ │ ├── AclReactiveCommandIntegrationTests.java │ │ │ │ │ └── ScriptingReactiveCommandIntegrationTests.java │ │ │ ├── tracing │ │ │ │ └── TestConfig.java │ │ │ ├── ScanArgsUnitTests.java │ │ │ ├── TestRedisPublisher.java │ │ │ ├── LimitUnitTests.java │ │ │ ├── cluster │ │ │ │ └── commands │ │ │ │ │ └── HashClusterCommandIntegrationTests.java │ │ │ ├── output │ │ │ │ └── SocketAddressOutputUnitTests.java │ │ │ ├── protocol │ │ │ │ └── TransactionalCommandUnitTests.java │ │ │ ├── ByteBufferCodec.java │ │ │ ├── ScanCursorUnitTests.java │ │ │ └── CopyArgsUnitTests.java │ │ │ ├── test │ │ │ ├── server │ │ │ │ └── RandomResponseServer.java │ │ │ ├── Delay.java │ │ │ ├── condition │ │ │ │ └── EnabledOnCommand.java │ │ │ ├── RoutingInvocationHandler.java │ │ │ ├── resource │ │ │ │ ├── FastShutdown.java │ │ │ │ └── DefaultRedisClient.java │ │ │ ├── MutableClock.java │ │ │ └── KeyValueStreamingAdapter.java │ │ │ ├── RedisBug.java │ │ │ ├── scenario │ │ │ └── MaintenanceNotificationCapture.java │ │ │ └── examples │ │ │ ├── ConnectToRedisSSL.java │ │ │ ├── ConnectToRedisUsingRedisSentinel.java │ │ │ ├── ConnectToElastiCacheMaster.java │ │ │ ├── ConnectToRedisClusterSSL.java │ │ │ └── ReadWriteExample.java │ └── jmh │ │ └── io │ │ └── lettuce │ │ └── core │ │ └── cluster │ │ └── EmptyRedisClusterClient.java └── assembly │ └── docs.xml ├── requirements.txt ├── .github ├── dependabot.yml ├── ISSUE_TEMPLATE │ ├── config.yml │ └── Feature_request.md ├── SECURITY.md ├── PULL_REQUEST_TEMPLATE.md └── workflows │ ├── release-drafter.yml │ ├── snapshot.yaml │ └── doctests.yml ├── .gitignore └── LICENSE /docs/index.md: -------------------------------------------------------------------------------- 1 | {% include 'README.md' %} -------------------------------------------------------------------------------- /docs/css/extra.css: -------------------------------------------------------------------------------- 1 | /* extra.css */ 2 | .md-header { 3 | background-color: #6DB340; 4 | } 5 | -------------------------------------------------------------------------------- /docs/static/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/redis/lettuce/HEAD/docs/static/favicon.ico -------------------------------------------------------------------------------- /src/main/resources/META-INF/services/io.lettuce.core.json.JsonParser: -------------------------------------------------------------------------------- 1 | io.lettuce.core.json.DefaultJsonParser -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | mkdocs~=1.6 2 | mkdocs-material~=9.5 3 | pymdown-extensions~=10.8 4 | mkdocs-macros-plugin~=1.0 5 | -------------------------------------------------------------------------------- /src/main/resources/META-INF/services/javax.enterprise.inject.spi.Extension: -------------------------------------------------------------------------------- 1 | io.lettuce.core.support.LettuceCdiExtension 2 | -------------------------------------------------------------------------------- /src/test/resources/docker-env/.env: -------------------------------------------------------------------------------- 1 | REDIS_ENV_WORK_DIR=../../../../work/docker 2 | REDIS_VERSION=8.4.0 3 | REDIS_STACK_VERSION=8.4.0 4 | -------------------------------------------------------------------------------- /src/test/resources/docker-env/.env.v8.0: -------------------------------------------------------------------------------- 1 | REDIS_ENV_WORK_DIR=../../../../work/docker 2 | REDIS_VERSION=8.0.2 3 | REDIS_STACK_VERSION=8.0.2 -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/api/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Standalone Redis connection API. 3 | */ 4 | package io.lettuce.core.api; 5 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/pubsub/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Pub/Sub connection classes. 3 | */ 4 | package io.lettuce.core.pubsub; 5 | -------------------------------------------------------------------------------- /src/test/resources/docker-env/.env.v7.2: -------------------------------------------------------------------------------- 1 | REDIS_ENV_WORK_DIR=../../../../work/docker 2 | REDIS_VERSION=7.2.9 3 | REDIS_STACK_VERSION=rs-7.2.0-v17 -------------------------------------------------------------------------------- /src/test/resources/docker-env/.env.v7.4: -------------------------------------------------------------------------------- 1 | REDIS_ENV_WORK_DIR=../../../../work/docker 2 | REDIS_VERSION=7.4.4 3 | REDIS_STACK_VERSION=rs-7.4.0-v5 -------------------------------------------------------------------------------- /src/test/resources/docker-env/.env.v8.2: -------------------------------------------------------------------------------- 1 | REDIS_ENV_WORK_DIR=../../../../work/docker 2 | REDIS_VERSION=8.2.2 3 | REDIS_STACK_VERSION=8.2.2 4 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/cluster/event/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Cluster event types. 3 | */ 4 | package io.lettuce.core.cluster.event; 5 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/event/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Event publishing and subscription. 3 | */ 4 | package io.lettuce.core.event; 5 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/json/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Support for the JSON Redis Module. 3 | */ 4 | package io.lettuce.core.json; 5 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/metrics/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Collectors for client metrics. 3 | */ 4 | package io.lettuce.core.metrics; 5 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/cluster/api/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Redis Cluster connection API. 3 | */ 4 | package io.lettuce.core.cluster.api; 5 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/codec/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Codecs for key/value type conversion. 3 | */ 4 | package io.lettuce.core.codec; 5 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/event/cluster/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Redis Cluster events. 3 | */ 4 | package io.lettuce.core.event.cluster; 5 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/event/command/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Command-related events. 3 | */ 4 | package io.lettuce.core.event.command; 5 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/protocol/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Redis protocol layer abstraction. 3 | */ 4 | package io.lettuce.core.protocol; 5 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/sentinel/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Redis Sentinel connection classes. 3 | */ 4 | package io.lettuce.core.sentinel; 5 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/api/push/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Interfaces to consume push messages. 3 | */ 4 | package io.lettuce.core.api.push; 5 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/event/metrics/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Metric events and publishing. 3 | */ 4 | package io.lettuce.core.event.metrics; 5 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/sentinel/api/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Redis Sentinel connection API. 3 | */ 4 | package io.lettuce.core.sentinel.api; 5 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/cluster/pubsub/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Redis Cluster Pub/Sub support. 3 | */ 4 | package io.lettuce.core.cluster.pubsub; 5 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/dynamic/intercept/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Invocation proxy support. 3 | */ 4 | package io.lettuce.core.dynamic.intercept; 5 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/event/connection/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Connection-related events. 3 | */ 4 | package io.lettuce.core.event.connection; 5 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/resource/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Client resource infrastructure providers. 3 | */ 4 | package io.lettuce.core.resource; 5 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/dynamic/batch/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Batching with Redis Command interfaces. 3 | */ 4 | package io.lettuce.core.dynamic.batch; 5 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/api/sync/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Standalone Redis API for synchronous executed commands. 3 | */ 4 | package io.lettuce.core.api.sync; 5 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/cluster/topology/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Support for cluster topology refresh. 3 | */ 4 | package io.lettuce.core.cluster.topology; 5 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/dynamic/parameter/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Parameter access and descriptors. 3 | */ 4 | package io.lettuce.core.dynamic.parameter; 5 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/models/role/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Model and parser for the {@code ROLE} output. 3 | */ 4 | package io.lettuce.core.models.role; 5 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/api/async/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Standalone Redis API for asynchronous executed commands. 3 | */ 4 | package io.lettuce.core.api.async; 5 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/api/reactive/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Standalone Redis API for reactive command execution. 3 | */ 4 | package io.lettuce.core.api.reactive; 5 | -------------------------------------------------------------------------------- /src/test/java/io/lettuce/category/SlowTests.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.category; 2 | 3 | /** 4 | * @author Mark Paluch 5 | */ 6 | public @interface SlowTests { 7 | 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/dynamic/support/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Support classes imported from the Spring Framework. 3 | */ 4 | package io.lettuce.core.dynamic.support; 5 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/event/jfr/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Event publishing specifically for Java Flight Recorder events. 3 | */ 4 | package io.lettuce.core.event.jfr; 5 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/cluster/api/sync/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Redis Cluster API for synchronous executed commands. 3 | */ 4 | package io.lettuce.core.cluster.api.sync; 5 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/dynamic/codec/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * {@link io.lettuce.core.codec.RedisCodec} resolution support. 3 | */ 4 | package io.lettuce.core.dynamic.codec; 5 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/dynamic/domain/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Core annotations to be used with Redis Command interfaces. 3 | */ 4 | package io.lettuce.core.dynamic.domain; 5 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/output/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Implementation of different output protocols including the Streaming API. 3 | */ 4 | package io.lettuce.core.output; 5 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/pubsub/api/async/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Pub/Sub Redis API for asynchronous executed commands. 3 | */ 4 | package io.lettuce.core.pubsub.api.async; 5 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/pubsub/api/sync/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Pub/Sub Redis API for synchronous executed commands. 3 | */ 4 | package io.lettuce.core.pubsub.api.sync; 5 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/tracing/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Integration of Brave and Micrometer Tracing for Lettuce Observability. 3 | */ 4 | package io.lettuce.core.tracing; 5 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/cluster/api/async/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Redis Cluster API for asynchronous executed commands. 3 | */ 4 | package io.lettuce.core.cluster.api.async; 5 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/cluster/api/push/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Interfaces to consume push messages using Redis Cluster. 3 | */ 4 | package io.lettuce.core.cluster.api.push; 5 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/cluster/api/reactive/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Redis Cluster API for reactive command execution. 3 | */ 4 | package io.lettuce.core.cluster.api.reactive; 5 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/pubsub/api/reactive/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Pub/Sub Redis API for reactive command execution. 3 | */ 4 | package io.lettuce.core.pubsub.api.reactive; 5 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/sentinel/api/async/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Redis Sentinel API for asynchronous executed commands. 3 | */ 4 | package io.lettuce.core.sentinel.api.async; 5 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/sentinel/api/sync/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Redis Sentinel API for synchronous executed commands. 3 | */ 4 | package io.lettuce.core.sentinel.api.sync; 5 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/cluster/models/slots/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Model and parser for the {@code CLUSTER SLOTS} output. 3 | */ 4 | package io.lettuce.core.cluster.models.slots; 5 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/cluster/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Client for Redis Cluster, see {@link io.lettuce.core.cluster.RedisClusterClient}. 3 | */ 4 | package io.lettuce.core.cluster; 5 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/dynamic/output/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * {@link io.lettuce.core.output.CommandOutput} resolution support. 3 | */ 4 | package io.lettuce.core.dynamic.output; 5 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/sentinel/api/reactive/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Redis Sentinel API for reactive command execution. 3 | */ 4 | package io.lettuce.core.sentinel.api.reactive; 5 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/cluster/pubsub/api/sync/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Redis Cluster Pub/Sub API for synchronous executed commands. 3 | */ 4 | package io.lettuce.core.cluster.pubsub.api.sync; 5 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/models/command/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Model and parser to for the {@code COMMAND} and {@code COMMAND INFO} output. 3 | */ 4 | package io.lettuce.core.models.command; 5 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/cluster/pubsub/api/async/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Redis Cluster Pub/Sub API for asynchronous executed commands. 3 | */ 4 | package io.lettuce.core.cluster.pubsub.api.async; 5 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/cluster/pubsub/api/reactive/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Redis Cluster Pub/Sub API for reactive command execution. 3 | */ 4 | package io.lettuce.core.cluster.pubsub.api.reactive; 5 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/models/stream/package-info.java: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * Model and parser for the Stream-related command output such as {@literal XPENDING}. 4 | */ 5 | package io.lettuce.core.models.stream; 6 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/dynamic/annotation/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Central domain abstractions to be used in combination with Redis Command interfaces. 3 | */ 4 | package io.lettuce.core.dynamic.annotation; 5 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/dynamic/segment/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Support for {@link io.lettuce.core.dynamic.segment.CommandSegments} and segment parsing. 3 | */ 4 | package io.lettuce.core.dynamic.segment; 5 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * The Redis client package containing {@link io.lettuce.core.RedisClient} for Redis Standalone and Redis Sentinel operations. 3 | */ 4 | package io.lettuce.core; 5 | -------------------------------------------------------------------------------- /src/test/resources/docker-env/ssl-test-cluster/config/node-7479/redis.conf: -------------------------------------------------------------------------------- 1 | port 7479 2 | save "" 3 | appendonly no 4 | cluster-enabled yes 5 | cluster-node-timeout 150 6 | cluster-announce-port 7445 7 | requirepass foobared -------------------------------------------------------------------------------- /src/test/resources/docker-env/ssl-test-cluster/config/node-7480/redis.conf: -------------------------------------------------------------------------------- 1 | port 7480 2 | save "" 3 | appendonly no 4 | cluster-enabled yes 5 | cluster-node-timeout 150 6 | cluster-announce-port 7444 7 | requirepass foobared -------------------------------------------------------------------------------- /src/test/resources/docker-env/ssl-test-cluster/config/node-7481/redis.conf: -------------------------------------------------------------------------------- 1 | port 7481 2 | save "" 3 | appendonly no 4 | cluster-enabled yes 5 | cluster-node-timeout 150 6 | cluster-announce-port 7445 7 | requirepass foobared -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | 3 | updates: 4 | - package-ecosystem: "maven" 5 | directory: "/" 6 | labels: 7 | - "type: dependency-upgrade" 8 | schedule: 9 | interval: "weekly" 10 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/dynamic/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Core package for Redis Command Interface support through {@link io.lettuce.core.dynamic.RedisCommandFactory}. 3 | */ 4 | package io.lettuce.core.dynamic; 5 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/cluster/models/partitions/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Model and parser for the {@code CLUSTER NODES} and {@code CLUSTER SLAVES} output. 3 | */ 4 | package io.lettuce.core.cluster.models.partitions; 5 | -------------------------------------------------------------------------------- /src/test/resources/docker-env/test-cluster/config/node-7379/redis.conf: -------------------------------------------------------------------------------- 1 | port 7379 2 | save "" 3 | appendonly no 4 | client-output-buffer-limit pubsub 256k 128k 5 5 | unixsocket /work/socket-7379 6 | cluster-enabled yes 7 | cluster-node-timeout 150 -------------------------------------------------------------------------------- /src/test/resources/docker-env/test-cluster/config/node-7380/redis.conf: -------------------------------------------------------------------------------- 1 | port 7380 2 | save "" 3 | appendonly no 4 | client-output-buffer-limit pubsub 256k 128k 5 5 | unixsocket /work/socket-7380 6 | cluster-enabled yes 7 | cluster-node-timeout 150 -------------------------------------------------------------------------------- /src/test/resources/docker-env/test-cluster/config/node-7381/redis.conf: -------------------------------------------------------------------------------- 1 | port 7381 2 | save "" 3 | appendonly no 4 | client-output-buffer-limit pubsub 256k 128k 5 5 | unixsocket /work/socket-7381 6 | cluster-enabled yes 7 | cluster-node-timeout 150 -------------------------------------------------------------------------------- /src/test/resources/docker-env/test-cluster/config/node-7382/redis.conf: -------------------------------------------------------------------------------- 1 | port 7382 2 | save "" 3 | appendonly no 4 | client-output-buffer-limit pubsub 256k 128k 5 5 | unixsocket /work/socket-7382 6 | cluster-enabled yes 7 | cluster-node-timeout 150 -------------------------------------------------------------------------------- /src/test/resources/docker-env/test-cluster/config/node-7383/redis.conf: -------------------------------------------------------------------------------- 1 | port 7383 2 | save "" 3 | appendonly no 4 | client-output-buffer-limit pubsub 256k 128k 5 5 | unixsocket /work/socket-7383 6 | cluster-enabled yes 7 | cluster-node-timeout 150 -------------------------------------------------------------------------------- /src/test/resources/docker-env/test-cluster/config/node-7384/redis.conf: -------------------------------------------------------------------------------- 1 | port 7384 2 | save "" 3 | appendonly no 4 | client-output-buffer-limit pubsub 256k 128k 5 5 | unixsocket /work/socket-7384 6 | cluster-enabled yes 7 | cluster-node-timeout 150 -------------------------------------------------------------------------------- /src/test/resources/docker-env/test-cluster/config/node-7582/redis.conf: -------------------------------------------------------------------------------- 1 | port 7582 2 | save "" 3 | appendonly no 4 | client-output-buffer-limit pubsub 256k 128k 5 5 | unixsocket /work/socket-7582 6 | cluster-enabled yes 7 | cluster-node-timeout 150 -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/internal/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Contains internal API. Classes in this package are part of the internal API and may change without further notice. 3 | * 4 | * @since 4.2 5 | */ 6 | package io.lettuce.core.internal; 7 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/support/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Supportive classes such as {@link io.lettuce.core.support.RedisClientCdiBean} for CDI support, connection pooling, and 3 | * client-side caching. 4 | */ 5 | package io.lettuce.core.support; 6 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/output/StreamingChannel.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.output; 2 | 3 | /** 4 | * Marker interface for streaming channels. 5 | * 6 | * @author Mark Paluch 7 | * @since 5.0 8 | */ 9 | public interface StreamingChannel { 10 | } 11 | -------------------------------------------------------------------------------- /src/test/resources/docker-env/test-cluster/config/node-7385/redis.conf: -------------------------------------------------------------------------------- 1 | port 7385 2 | save "" 3 | appendonly no 4 | client-output-buffer-limit pubsub 256k 128k 5 5 | unixsocket /work/socket-7385 6 | cluster-enabled yes 7 | cluster-node-timeout 150 8 | requirepass foobared -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/event/Event.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.event; 2 | 3 | /** 4 | * 5 | * Marker-interface for events that are published over the event bus. 6 | * 7 | * @author Mark Paluch 8 | * @since 3.4 9 | */ 10 | public interface Event { 11 | } 12 | -------------------------------------------------------------------------------- /src/test/resources/docker-env/redis-standalone-5-client-cert/config/node-6478/redis.conf: -------------------------------------------------------------------------------- 1 | port 6485 2 | tls-port 6445 3 | #tls-auth-clients no 4 | save "" 5 | appendonly no 6 | client-output-buffer-limit pubsub 256k 128k 5 7 | enable-debug-command yes 8 | replica-announce-ip localhost -------------------------------------------------------------------------------- /src/test/resources/docker-env/redis-standalone-1/config/node-6486/redis.conf: -------------------------------------------------------------------------------- 1 | port 6486 2 | save "" 3 | appendonly no 4 | client-output-buffer-limit pubsub 256k 128k 5 5 | unixsocket /work/socket-6486 6 | unixsocketperm 777 7 | enable-debug-command yes 8 | replica-announce-ip localhost -------------------------------------------------------------------------------- /src/test/resources/docker-env/redis-standalone-2/config/node-6480/redis.conf: -------------------------------------------------------------------------------- 1 | port 6480 2 | save "" 3 | appendonly no 4 | client-output-buffer-limit pubsub 256k 128k 5 5 | unixsocket /work/socket-6480 6 | unixsocketperm 777 7 | enable-debug-command yes 8 | replica-announce-ip localhost -------------------------------------------------------------------------------- /src/test/resources/docker-env/redis-standalone-3/config/node-6481/redis.conf: -------------------------------------------------------------------------------- 1 | port 6481 2 | save "" 3 | appendonly no 4 | client-output-buffer-limit pubsub 256k 128k 5 5 | unixsocket /work/socket-6481 6 | unixsocketperm 777 7 | enable-debug-command yes 8 | replica-announce-ip localhost -------------------------------------------------------------------------------- /src/test/resources/docker-env/redis-standalone-4/config/node-6484/redis.conf: -------------------------------------------------------------------------------- 1 | port 6484 2 | save "" 3 | appendonly no 4 | client-output-buffer-limit pubsub 256k 128k 5 5 | unixsocket /work/socket-6484 6 | unixsocketperm 777 7 | enable-debug-command yes 8 | replica-announce-ip localhost -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/search/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2025, Redis Ltd. and Contributors 3 | * All rights reserved. 4 | * 5 | * Licensed under the MIT License. 6 | */ 7 | /** 8 | * Support for the RediSearch features. 9 | */ 10 | package io.lettuce.core.search; 11 | -------------------------------------------------------------------------------- /src/test/resources/META-INF/beans.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/test/resources/docker-env/redis-standalone-0/config/node-6478/redis.conf: -------------------------------------------------------------------------------- 1 | port 6478 2 | tls-port 6444 3 | tls-auth-clients no 4 | save "" 5 | appendonly no 6 | client-output-buffer-limit pubsub 256k 128k 5 7 | enable-debug-command yes 8 | unixsocket /work/socket-6478 9 | unixsocketperm 777 10 | replica-announce-ip localhost -------------------------------------------------------------------------------- /src/test/resources/docker-env/redis-standalone-1/config/node-6479/redis.conf: -------------------------------------------------------------------------------- 1 | port 6479 2 | tls-port 6443 3 | tls-auth-clients no 4 | save "" 5 | appendonly no 6 | client-output-buffer-limit pubsub 256k 128k 5 7 | enable-debug-command yes 8 | unixsocket /work/socket-6479 9 | unixsocketperm 777 10 | replica-announce-ip localhost -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | appendonlydir/ 3 | *.rdb 4 | *.aof 5 | - 6 | atlassian-ide-plugin.xml 7 | *.iml 8 | redis-git 9 | *.releaseBackup 10 | release.properties 11 | work/ 12 | .project 13 | .classpath 14 | .settings 15 | dependency-reduced-pom.xml 16 | .idea 17 | .flattened-pom.xml 18 | *.java-version 19 | *.DS_Store 20 | .vscode* -------------------------------------------------------------------------------- /src/test/resources/docker-env/redis-standalone-sentinel-controlled/config/node-6482/redis.conf: -------------------------------------------------------------------------------- 1 | port 6482 2 | tls-port 8443 3 | tls-auth-clients no 4 | save "" 5 | appendonly no 6 | client-output-buffer-limit pubsub 256k 128k 5 7 | unixsocket /work/socket-6482 8 | unixsocketperm 777 9 | enable-debug-command yes 10 | replica-announce-ip localhost -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/dynamic/Commands.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.dynamic; 2 | 3 | /** 4 | * Marker interface for dynamic Redis commands. Typically used by Redis Command Interfaces as extension point to discover 5 | * interface declarations. 6 | * 7 | * @author Mark Paluch 8 | * @since 5.0 9 | */ 10 | public interface Commands { 11 | } 12 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | contact_links: 2 | - name: Discussions 3 | url: https://github.com/lettuce-io/lettuce-core/discussions 4 | about: Use GitHub discussions to discuss an enhancement proposal or if you have a question 5 | - name: Questions 6 | url: https://discord.gg/redis 7 | about: Please ask questions on Discord or StackOverflow. 8 | -------------------------------------------------------------------------------- /src/test/resources/docker-env/redis-standalone-sentinel-controlled/config/node-6483/redis.conf: -------------------------------------------------------------------------------- 1 | port 6483 2 | tls-port 8444 3 | tls-auth-clients no 4 | save "" 5 | appendonly no 6 | client-output-buffer-limit pubsub 256k 128k 5 7 | unixsocket /work/socket-6483 8 | unixsocketperm 777 9 | enable-debug-command yes 10 | slaveof 127.0.0.1 6482 11 | replica-announce-ip localhost -------------------------------------------------------------------------------- /src/main/resources/META-INF/native-image/io.lettuce/lettuce-core/native-image.properties: -------------------------------------------------------------------------------- 1 | Args=--initialize-at-build-time=io.lettuce.core.metrics.DefaultCommandLatencyCollector,io.lettuce.core.metrics.DefaultCommandLatencyCollector$NoOpPauseDetectorWrapper,io.lettuce.core.metrics.DefaultCommandLatencyCollector$DefaultPauseDetectorWrapper,io.lettuce.core.internal.LettuceClassUtils 2 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/tracing/TracerProvider.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.tracing; 2 | 3 | /** 4 | * Interface to obtain a {@link Tracer}. 5 | * 6 | * @author Mark Paluch 7 | * @since 5.1 8 | */ 9 | @FunctionalInterface 10 | public interface TracerProvider { 11 | 12 | /** 13 | * @return the {@link Tracer}. 14 | */ 15 | Tracer getTracer(); 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/test/java/io/lettuce/core/support/PersonDB.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.support; 2 | 3 | import java.lang.annotation.Retention; 4 | import java.lang.annotation.RetentionPolicy; 5 | 6 | import javax.inject.Qualifier; 7 | 8 | /** 9 | * @author Mark Paluch 10 | * @since 3.0 11 | */ 12 | @Retention(RetentionPolicy.RUNTIME) 13 | @Qualifier 14 | @interface PersonDB { 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/event/connection/ConnectionEvent.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.event.connection; 2 | 3 | import io.lettuce.core.ConnectionId; 4 | import io.lettuce.core.event.Event; 5 | 6 | /** 7 | * Interface for Connection-related events 8 | * 9 | * @author Mark Paluch 10 | * @since 3.4 11 | */ 12 | public interface ConnectionEvent extends ConnectionId, Event { 13 | 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/tracing/TraceContext.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.tracing; 2 | 3 | /** 4 | * Marker interface for a context propagation of parent and child spans. Subclasses may add their propagation metadata. 5 | * 6 | * @author Mark Paluch 7 | * @since 5.1 8 | * 9 | */ 10 | public interface TraceContext { 11 | 12 | TraceContext EMPTY = new TraceContext() { 13 | }; 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/test/java/io/lettuce/test/server/RandomResponseServer.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.test.server; 2 | 3 | /** 4 | * Tiny netty server to generate random base64 data on message reception. 5 | * 6 | * @author Mark Paluch 7 | */ 8 | public class RandomResponseServer extends MockTcpServer { 9 | 10 | public RandomResponseServer() { 11 | addHandler(RandomServerHandler::new); 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/dynamic/annotation/Key.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.dynamic.annotation; 2 | 3 | import java.lang.annotation.*; 4 | 5 | /** 6 | * Marker annotation to declare a method parameter as key. 7 | * 8 | * @author Mark Paluch 9 | * @see Value 10 | * @since 5.0 11 | */ 12 | @Retention(RetentionPolicy.RUNTIME) 13 | @Target(ElementType.PARAMETER) 14 | @Documented 15 | public @interface Key { 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/dynamic/annotation/Value.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.dynamic.annotation; 2 | 3 | import java.lang.annotation.*; 4 | 5 | /** 6 | * Marker annotation to declare a method parameter as value. 7 | * 8 | * @author Mark Paluch 9 | * @see Key 10 | * @since 5.0 11 | */ 12 | @Retention(RetentionPolicy.RUNTIME) 13 | @Target(ElementType.PARAMETER) 14 | @Documented 15 | public @interface Value { 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/dynamic/intercept/InvocationTargetProvider.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.dynamic.intercept; 2 | 3 | /** 4 | * Provides an invocation target object. 5 | * 6 | * @see MethodInterceptor 7 | * @author Mark Paluch 8 | * @since 5.0 9 | */ 10 | public interface InvocationTargetProvider { 11 | 12 | /** 13 | * @return the invocation target. 14 | */ 15 | Object getInvocationTarget(); 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/protocol/RedisProtocolException.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.protocol; 2 | 3 | import io.lettuce.core.RedisException; 4 | 5 | /** 6 | * Exception thrown on Redis protocol failures. 7 | * 8 | * @author Mark Paluch 9 | * @since 6.0 10 | */ 11 | public class RedisProtocolException extends RedisException { 12 | 13 | public RedisProtocolException(String msg) { 14 | super(msg); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/test/resources/docker-env/redis-standalone-sentinel-controlled/config/node-sentinel-26380/redis.conf: -------------------------------------------------------------------------------- 1 | port 26380 2 | sentinel monitor mymaster localhost 6482 1 3 | sentinel announce-hostnames yes 4 | sentinel resolve-hostnames yes 5 | sentinel announce-ip localhost 6 | sentinel down-after-milliseconds mymaster 200 7 | sentinel failover-timeout mymaster 200 8 | sentinel parallel-syncs mymaster 1 9 | unixsocket /work/socket-26380 10 | unixsocketperm 777 -------------------------------------------------------------------------------- /.github/SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Supported Versions 4 | 5 | Currently maintained 6 | 7 | Information about supported Lettuce versions can be found on the [Lettuce version support page](https://github.com/lettuce-io/lettuce-core/wiki/Lettuce-Versions) in the [Lettuce wiki](https://github.com/lettuce-io/lettuce-core/wiki). 8 | 9 | ## Reporting a Vulnerability 10 | 11 | Please open an issue, without details. We will contact you then. 12 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/models/role/RedisNodeDescription.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.models.role; 2 | 3 | import io.lettuce.core.RedisURI; 4 | 5 | /** 6 | * Description of a single Redis Node. 7 | * 8 | * @author Mark Paluch 9 | * @since 4.0 10 | */ 11 | public interface RedisNodeDescription extends RedisInstance { 12 | 13 | /** 14 | * 15 | * @return the URI of the node 16 | */ 17 | RedisURI getUri(); 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/protocol/DecoratedCommand.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.protocol; 2 | 3 | /** 4 | * A decorated command allowing access to the underlying {@link #getDelegate()}. 5 | * 6 | * @author Mark Paluch 7 | */ 8 | public interface DecoratedCommand { 9 | 10 | /** 11 | * The underlying command. 12 | * 13 | * @return never {@code null}. 14 | */ 15 | RedisCommand getDelegate(); 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/test/resources/docker-env/ssl-test-cluster/config/node-7479/nodes.conf: -------------------------------------------------------------------------------- 1 | cf2354ef19ee813a962350b51438314aebce1fe2 127.0.0.1:7479@17479 myself,master - 0 1578163609000 0 connected 0-10000 2 | cac8e053dd6f85fab470be57d29dcbac2a4b85c4 127.0.0.1:7480@17480 slave cf2354ef19ee813a962350b51438314aebce1fe2 0 1578163609301 1 connected 3 | 6554e5b1b158dccd4b1d9ca294a3e46a2d3e556d 127.0.0.1:7481@17481 master - 0 1578163609301 2 connected 10001-16383 4 | vars currentEpoch 2 lastVoteEpoch 0 -------------------------------------------------------------------------------- /src/test/resources/docker-env/ssl-test-cluster/config/node-7481/nodes.conf: -------------------------------------------------------------------------------- 1 | cac8e053dd6f85fab470be57d29dcbac2a4b85c4 127.0.0.1:7480@17480 slave cf2354ef19ee813a962350b51438314aebce1fe2 0 1578163609279 1 connected 2 | cf2354ef19ee813a962350b51438314aebce1fe2 127.0.0.1:7479@17479 master - 0 1578163609279 0 connected 0-10000 3 | 6554e5b1b158dccd4b1d9ca294a3e46a2d3e556d 127.0.0.1:7481@17481 myself,master - 0 1578163609000 2 connected 10001-16383 4 | vars currentEpoch 2 lastVoteEpoch 0 -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/cluster/event/AskRedirectionEvent.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.cluster.event; 2 | 3 | /** 4 | * Event emitted on a {@code ASK} redirection. 5 | * 6 | * @author Mark Paluch 7 | * @since 6.1 8 | */ 9 | public class AskRedirectionEvent extends RedirectionEventSupport { 10 | 11 | public AskRedirectionEvent(String command, String key, int slot, String message) { 12 | super(command, key, slot, message); 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/test/resources/docker-env/ssl-test-cluster/config/node-7480/nodes.conf: -------------------------------------------------------------------------------- 1 | cf2354ef19ee813a962350b51438314aebce1fe2 127.0.0.1:7479@17479 master - 0 1578163609245 0 connected 0-10000 2 | cac8e053dd6f85fab470be57d29dcbac2a4b85c4 127.0.0.1:7480@17480 myself,slave cf2354ef19ee813a962350b51438314aebce1fe2 0 1578163609000 1 connected 3 | 6554e5b1b158dccd4b1d9ca294a3e46a2d3e556d 127.0.0.1:7481@17481 master - 0 1578163609245 2 connected 10001-16383 4 | vars currentEpoch 2 lastVoteEpoch 0 -------------------------------------------------------------------------------- /src/test/resources/docker-env/redis-standalone-4/config/node-sentinel-26381/redis.conf: -------------------------------------------------------------------------------- 1 | port 26381 2 | sentinel monitor mymaster localhost 6484 1 3 | sentinel announce-hostnames yes 4 | sentinel resolve-hostnames yes 5 | sentinel announce-ip localhost 6 | sentinel down-after-milliseconds mymaster 200 7 | sentinel failover-timeout mymaster 200 8 | sentinel parallel-syncs mymaster 1 9 | sentinel auth-pass mymaster foobared 10 | unixsocket /work/socket-26381 11 | unixsocketperm 777 -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/cluster/event/MovedRedirectionEvent.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.cluster.event; 2 | 3 | /** 4 | * Event emitted on a {@code MOVED} redirection. 5 | * 6 | * @author Mark Paluch 7 | * @since 6.1 8 | */ 9 | public class MovedRedirectionEvent extends RedirectionEventSupport { 10 | 11 | public MovedRedirectionEvent(String command, String key, int slot, String message) { 12 | super(command, key, slot, message); 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/protocol/HasQueuedCommands.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.protocol; 2 | 3 | import java.util.Collection; 4 | 5 | /** 6 | * Interface to be implemented by classes that queue commands. Implementors of this class need to expose their queue to control 7 | * all queues by maintenance and cleanup processes. 8 | * 9 | * @author Mark Paluch 10 | */ 11 | interface HasQueuedCommands { 12 | 13 | Collection> drainQueue(); 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/KeyScanCursor.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | /** 7 | * Cursor providing a list of keys. 8 | * 9 | * @param Key type. 10 | * @author Mark Paluch 11 | * @since 3.0 12 | */ 13 | public class KeyScanCursor extends ScanCursor { 14 | 15 | private final List keys = new ArrayList<>(); 16 | 17 | public List getKeys() { 18 | return keys; 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/event/EventPublisherOptions.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.event; 2 | 3 | import java.time.Duration; 4 | 5 | /** 6 | * Configuration interface for command latency collection. 7 | * 8 | * @author Mark Paluch 9 | */ 10 | public interface EventPublisherOptions { 11 | 12 | /** 13 | * Returns the interval for emit metrics. 14 | * 15 | * @return the interval for emit metrics 16 | */ 17 | Duration eventEmitInterval(); 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/test/java/io/lettuce/RedisBug.java: -------------------------------------------------------------------------------- 1 | package io.lettuce; 2 | 3 | import java.lang.annotation.*; 4 | 5 | import org.junit.jupiter.api.Disabled; 6 | 7 | /** 8 | * Annotations for tests disabled due to a Redis bug. 9 | * 10 | * @author Mark Paluch 11 | */ 12 | @Target({ ElementType.TYPE, ElementType.METHOD }) 13 | @Retention(RetentionPolicy.RUNTIME) 14 | @Documented 15 | @Disabled("Redis Bug") 16 | public @interface RedisBug { 17 | 18 | String value() default ""; 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/test/resources/docker-env/redis-standalone-sentinel-controlled/config/node-sentinel-26379/redis.conf: -------------------------------------------------------------------------------- 1 | port 26379 2 | tls-port 26822 3 | tls-auth-clients no 4 | sentinel monitor mymaster localhost 6482 1 5 | sentinel announce-hostnames yes 6 | sentinel resolve-hostnames yes 7 | sentinel announce-ip localhost 8 | sentinel down-after-milliseconds mymaster 200 9 | sentinel failover-timeout mymaster 200 10 | sentinel parallel-syncs mymaster 1 11 | unixsocket /work/socket-26379 12 | unixsocketperm 777 13 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/StreamScanCursor.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core; 2 | 3 | /** 4 | * Cursor result using the Streaming API. Provides the count of retrieved elements. 5 | * 6 | * @author Mark Paluch 7 | * @since 3.0 8 | */ 9 | public class StreamScanCursor extends ScanCursor { 10 | 11 | private long count; 12 | 13 | public long getCount() { 14 | return count; 15 | } 16 | 17 | public void setCount(long count) { 18 | this.count = count; 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/test/resources/.env.entraid: -------------------------------------------------------------------------------- 1 | AZURE_SP_OID= 2 | AZURE_CLIENT_ID= 3 | AZURE_CLIENT_SECRET= 4 | AZURE_REDIS_SCOPES=https://redis.azure.com/.default 5 | AZURE_AUTHORITY=https://login.microsoftonline.com/ 6 | # Redis standalone db with Azure enabled authentication 7 | REDIS_AZURE_HOST= 8 | REDIS_AZURE_PORT=6379 9 | # Redis cluster db with Azure enabled authentication & osscluster API enabled 10 | REDIS_AZURE_CLUSTER_HOST= 11 | REDIS_AZURE_CLUSTER_PORT=6379 12 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/protocol/ConnectionIntent.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.protocol; 2 | 3 | /** 4 | * Enumeration of intentions for how a connection is going to be used. 5 | * 6 | * @author Mark Paluch 7 | * @since 6.2 8 | */ 9 | public enum ConnectionIntent { 10 | 11 | /** 12 | * Intention to use read-only operations through a connection. 13 | */ 14 | READ, 15 | 16 | /** 17 | * Intention to run read or write commands through a connection. 18 | */ 19 | WRITE; 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/SslVerifyMode.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core; 2 | 3 | /** 4 | * Enumeration of SSL/TLS verification modes. 5 | * 6 | * @author Mark Paluch 7 | * @since 6.1 8 | */ 9 | public enum SslVerifyMode { 10 | 11 | /** 12 | * No verification at all. 13 | */ 14 | NONE, 15 | 16 | /** 17 | * Verify the CA and certificate without verifying that the hostname matches. 18 | */ 19 | CA, 20 | 21 | /** 22 | * Full certificate verification. 23 | */ 24 | FULL; 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/resource/ConstantDelay.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.resource; 2 | 3 | import java.time.Duration; 4 | 5 | /** 6 | * {@link Delay} with a constant delay for each attempt. 7 | * 8 | * @author Mark Paluch 9 | */ 10 | class ConstantDelay extends Delay { 11 | 12 | private final Duration delay; 13 | 14 | ConstantDelay(Duration delay) { 15 | this.delay = delay; 16 | } 17 | 18 | @Override 19 | public Duration createDelay(long attempt) { 20 | return delay; 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/ValueScanCursor.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | /** 7 | * Cursor providing a list of values. 8 | * 9 | * @param Value type. 10 | * @author Mark Paluch 11 | * @since 3.0 12 | */ 13 | public class ValueScanCursor extends ScanCursor { 14 | 15 | private final List values = new ArrayList<>(); 16 | 17 | public ValueScanCursor() { 18 | } 19 | 20 | public List getValues() { 21 | return values; 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/cluster/api/async/AsyncNodeSelection.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.cluster.api.async; 2 | 3 | import io.lettuce.core.api.async.RedisAsyncCommands; 4 | import io.lettuce.core.cluster.api.NodeSelectionSupport; 5 | 6 | /** 7 | * Node selection with access to asynchronous executed commands on the set. 8 | * 9 | * @author Mark Paluch 10 | * @since 4.0 11 | */ 12 | public interface AsyncNodeSelection 13 | extends NodeSelectionSupport, NodeSelectionAsyncCommands> { 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/dynamic/annotation/Param.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.dynamic.annotation; 2 | 3 | import java.lang.annotation.*; 4 | 5 | /** 6 | * Annotation to bind method parameters using their name. 7 | * 8 | * @author Mark Paluch 9 | * @see Key 10 | * @since 5.0 11 | */ 12 | @Retention(RetentionPolicy.RUNTIME) 13 | @Target(ElementType.PARAMETER) 14 | @Documented 15 | public @interface Param { 16 | 17 | /** 18 | * Name of the parameter. 19 | * 20 | * @return 21 | */ 22 | String value(); 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/cluster/pubsub/api/sync/PubSubNodeSelection.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.cluster.pubsub.api.sync; 2 | 3 | import io.lettuce.core.cluster.api.NodeSelectionSupport; 4 | import io.lettuce.core.pubsub.api.sync.RedisPubSubCommands; 5 | 6 | /** 7 | * Node selection with access to {@link RedisPubSubCommands}. 8 | * 9 | * @author Mark Paluch 10 | * @since 4.4 11 | */ 12 | public interface PubSubNodeSelection 13 | extends NodeSelectionSupport, NodeSelectionPubSubCommands> { 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/test/resources/docker-env/test-cluster/config/node-7382/nodes.conf: -------------------------------------------------------------------------------- 1 | c2043458aa5646cee429fdd5e3c18220dddf2ce5 127.0.0.1:7380 master - 0 1434887920102 0 connected 12000-16383 2 | 1c541b6daf98719769e6aacf338a7d81f108a180 127.0.0.1:7381 slave 27f88788f03a86296b7d860152f4ae24ee59c8c9 0 1434887920102 3 connected 3 | 2c07344ffa94ede5ea57a2367f190af6144c1adb 127.0.0.1:7382 myself,slave c2043458aa5646cee429fdd5e3c18220dddf2ce5 0 0 2 connected 4 | 27f88788f03a86296b7d860152f4ae24ee59c8c9 127.0.0.1:7379 master - 0 1434887920102 1 connected 0-11999 5 | vars currentEpoch 3 lastVoteEpoch 0 -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/output/ArrayOutput.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.output; 2 | 3 | import io.lettuce.core.codec.RedisCodec; 4 | 5 | /** 6 | * {@link java.util.List} of objects and lists to support dynamic nested structures (List with mixed content of values and 7 | * sublists). 8 | * 9 | * @param Key type. 10 | * @param Value type. 11 | * @author Mark Paluch 12 | */ 13 | public class ArrayOutput extends NestedMultiOutput { 14 | 15 | public ArrayOutput(RedisCodec codec) { 16 | super(codec); 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/output/ValueStreamingChannel.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.output; 2 | 3 | /** 4 | * Streaming API for multiple Keys. You can implement this interface in order to receive a call to {@code onValue} on every 5 | * value. 6 | * 7 | * @param Value type. 8 | * @author Mark Paluch 9 | * @since 3.0 10 | */ 11 | @FunctionalInterface 12 | public interface ValueStreamingChannel { 13 | 14 | /** 15 | * Called on every incoming value. 16 | * 17 | * @param value the value 18 | */ 19 | void onValue(V value); 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/MapScanCursor.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core; 2 | 3 | import java.util.LinkedHashMap; 4 | import java.util.Map; 5 | 6 | /** 7 | * Scan cursor for maps. 8 | * 9 | * @param Key type. 10 | * @param Value type. 11 | * @author Mark Paluch 12 | * @since 3.0 13 | */ 14 | public class MapScanCursor extends ScanCursor { 15 | 16 | private final Map map = new LinkedHashMap<>(); 17 | 18 | /** 19 | * 20 | * @return the map result. 21 | */ 22 | public Map getMap() { 23 | return map; 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/api/push/PushListener.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.api.push; 2 | 3 | /** 4 | * Interface to be implemented by push message listeners that are interested in listening to {@link PushMessage}. Requires Redis 5 | * 6+ using RESP3. 6 | * 7 | * @author Mark Paluch 8 | * @since 6.0 9 | * @see PushMessage 10 | */ 11 | @FunctionalInterface 12 | public interface PushListener { 13 | 14 | /** 15 | * Handle a push message. 16 | * 17 | * @param message message to respond to. 18 | */ 19 | void onPushMessage(PushMessage message); 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/cluster/api/sync/NodeSelection.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.cluster.api.sync; 2 | 3 | import io.lettuce.core.api.sync.RedisCommands; 4 | import io.lettuce.core.cluster.api.NodeSelectionSupport; 5 | 6 | /** 7 | * Node selection with access to synchronous executed commands on the set. Commands are triggered concurrently to the selected 8 | * nodes and synchronized afterwards. 9 | * 10 | * @author Mark Paluch 11 | * @since 4.0 12 | */ 13 | public interface NodeSelection extends NodeSelectionSupport, NodeSelectionCommands> { 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/cluster/pubsub/api/async/PubSubAsyncNodeSelection.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.cluster.pubsub.api.async; 2 | 3 | import io.lettuce.core.cluster.api.NodeSelectionSupport; 4 | import io.lettuce.core.pubsub.api.async.RedisPubSubAsyncCommands; 5 | 6 | /** 7 | * Node selection with access to asynchronous executed commands on the set. 8 | * 9 | * @author Mark Paluch 10 | * @since 4.4 11 | */ 12 | public interface PubSubAsyncNodeSelection 13 | extends NodeSelectionSupport, NodeSelectionPubSubAsyncCommands> { 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/test/java/io/lettuce/core/RedisClientListenerIntegrationTests.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core; 2 | 3 | import org.junit.jupiter.api.Tag; 4 | import org.junit.jupiter.api.extension.ExtendWith; 5 | 6 | import io.lettuce.test.LettuceExtension; 7 | 8 | import static io.lettuce.TestTags.INTEGRATION_TEST; 9 | 10 | /** 11 | * Integration tests for {@link RedisConnectionStateListener} via {@link RedisClient}. 12 | * 13 | * @author Mark Paluch 14 | */ 15 | @Tag(INTEGRATION_TEST) 16 | @ExtendWith(LettuceExtension.class) 17 | class RedisClientListenerIntegrationTests extends TestSupport { 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/test/resources/docker-env/test-cluster/config/node-7379/nodes.conf: -------------------------------------------------------------------------------- 1 | c2043458aa5646cee429fdd5e3c18220dddf2ce5 127.0.0.1:7380 master - 1434887920102 1434887920002 0 connected 12000-16383 2 | 27f88788f03a86296b7d860152f4ae24ee59c8c9 127.0.0.1:7379 myself,master - 0 0 1 connected 0-11999 3 | 2c07344ffa94ede5ea57a2367f190af6144c1adb 127.0.0.1:7382 slave c2043458aa5646cee429fdd5e3c18220dddf2ce5 1434887920102 1434887920002 2 connected 4 | 1c541b6daf98719769e6aacf338a7d81f108a180 127.0.0.1:7381 slave 27f88788f03a86296b7d860152f4ae24ee59c8c9 1434887920102 1434887920002 3 connected 5 | vars currentEpoch 3 lastVoteEpoch 0 -------------------------------------------------------------------------------- /src/test/resources/docker-env/test-cluster/config/node-7380/nodes.conf: -------------------------------------------------------------------------------- 1 | 2c07344ffa94ede5ea57a2367f190af6144c1adb 127.0.0.1:7382 slave c2043458aa5646cee429fdd5e3c18220dddf2ce5 1434887920102 1434887920002 2 connected 2 | 27f88788f03a86296b7d860152f4ae24ee59c8c9 127.0.0.1:7379 master - 1434887920102 1434887920002 1 connected 0-11999 3 | 1c541b6daf98719769e6aacf338a7d81f108a180 127.0.0.1:7381 slave 27f88788f03a86296b7d860152f4ae24ee59c8c9 1434887920102 1434887920002 3 connected 4 | c2043458aa5646cee429fdd5e3c18220dddf2ce5 127.0.0.1:7380 myself,master - 0 0 0 connected 12000-16383 5 | vars currentEpoch 3 lastVoteEpoch 0 -------------------------------------------------------------------------------- /src/test/resources/docker-env/test-cluster/config/node-7381/nodes.conf: -------------------------------------------------------------------------------- 1 | 1c541b6daf98719769e6aacf338a7d81f108a180 127.0.0.1:7381 myself,slave 27f88788f03a86296b7d860152f4ae24ee59c8c9 0 0 3 connected 2 | 2c07344ffa94ede5ea57a2367f190af6144c1adb 127.0.0.1:7382 slave c2043458aa5646cee429fdd5e3c18220dddf2ce5 1434887920102 1434887920002 2 connected 3 | c2043458aa5646cee429fdd5e3c18220dddf2ce5 127.0.0.1:7380 master - 1434887920102 1434887920002 0 connected 12000-16383 4 | 27f88788f03a86296b7d860152f4ae24ee59c8c9 127.0.0.1:7379 master - 1434887920102 1434887920002 1 connected 0-11999 5 | vars currentEpoch 3 lastVoteEpoch 0 -------------------------------------------------------------------------------- /src/test/resources/docker-env/test-cluster/config/node-7582/nodes.conf: -------------------------------------------------------------------------------- 1 | c2043458aa5646cee429fdd5e3c18220dddf2ce5 127.0.0.1:7580 master - 1434887920102 1434887920002 0 connected 10001-16383 2 | 27f88788f03a86296b7d860152f4ae24ee59c8c9 127.0.0.1:7579 myself,master - 0 0 1 connected 0-10000 3 | 2c07344ffa94ede5ea57a2367f190af6144c1adb 127.0.0.1:7582 slave c2043458aa5646cee429fdd5e3c18220dddf2ce5 1434887920102 1434887920002 2 connected 4 | 1c541b6daf98719769e6aacf338a7d81f108a180 127.0.0.1:7581 slave 27f88788f03a86296b7d860152f4ae24ee59c8c9 1434887920102 1434887920002 3 connected 5 | vars currentEpoch 3 lastVoteEpoch 0 -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/resource/DefaultThreadFactoryProvider.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.resource; 2 | 3 | import java.util.concurrent.ThreadFactory; 4 | 5 | import io.netty.util.concurrent.DefaultThreadFactory; 6 | 7 | /** 8 | * Default {@link ThreadFactoryProvider} implementation. 9 | * 10 | * @author Mark Paluch 11 | */ 12 | enum DefaultThreadFactoryProvider implements ThreadFactoryProvider { 13 | 14 | INSTANCE; 15 | 16 | @Override 17 | public ThreadFactory getThreadFactory(String poolName) { 18 | return new DefaultThreadFactory(poolName, true); 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/test/java/io/lettuce/scenario/MaintenanceNotificationCapture.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.scenario; 2 | 3 | /** 4 | * Interface for capturing Redis Enterprise maintenance event notifications. This allows different capture implementations to 5 | * work with the same push notification monitoring utility. 6 | */ 7 | public interface MaintenanceNotificationCapture { 8 | 9 | /** 10 | * Captures a maintenance notification in RESP3 format 11 | * 12 | * @param notification the notification string in RESP3 format 13 | */ 14 | void captureNotification(String notification); 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/output/KeyStreamingChannel.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.output; 2 | 3 | /** 4 | * Streaming API for multiple Keys. You can implement this interface in order to receive a call to {@code onKey} on every key. 5 | * Key uniqueness is not guaranteed. 6 | * 7 | * @param Key type. 8 | * @author Mark Paluch 9 | * @since 3.0 10 | */ 11 | @FunctionalInterface 12 | public interface KeyStreamingChannel extends StreamingChannel { 13 | 14 | /** 15 | * Called on every incoming key. 16 | * 17 | * @param key the key 18 | */ 19 | void onKey(K key); 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/cluster/UnknownPartitionException.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.cluster; 2 | 3 | /** 4 | * Exception thrown when an unknown partition is requested. 5 | * 6 | * @author Mark Paluch 7 | * @since 5.1 8 | */ 9 | @SuppressWarnings("serial") 10 | public class UnknownPartitionException extends PartitionException { 11 | 12 | /** 13 | * Create a {@code UnknownPartitionException} with the specified detail message. 14 | * 15 | * @param msg the detail message. 16 | */ 17 | public UnknownPartitionException(String msg) { 18 | super(msg); 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/event/connection/AuthenticationEvent.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2024, Redis Ltd. and Contributors 3 | * All rights reserved. 4 | * 5 | * Licensed under the MIT License. 6 | */ 7 | package io.lettuce.core.event.connection; 8 | 9 | import io.lettuce.core.event.Event; 10 | 11 | /** 12 | * Interface for Connection authentication events 13 | * 14 | * @author Ivo Gaydajiev 15 | * @since 6.6.0 16 | */ 17 | public interface AuthenticationEvent extends Event { 18 | 19 | /** 20 | * @return the endpoint ID associated with this event 21 | */ 22 | String getEpId(); 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/ScoredValueScanCursor.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | /** 7 | * Cursor providing a list of {@link io.lettuce.core.ScoredValue} 8 | * 9 | * @param Value type. 10 | * @author Mark Paluch 11 | * @since 3.0 12 | */ 13 | public class ScoredValueScanCursor extends ScanCursor { 14 | 15 | private final List> values = new ArrayList<>(); 16 | 17 | public ScoredValueScanCursor() { 18 | } 19 | 20 | public List> getValues() { 21 | return values; 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/json/RedisJsonException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2024, Redis Ltd. and Contributors 3 | * All rights reserved. 4 | * 5 | * Licensed under the MIT License. 6 | */ 7 | 8 | package io.lettuce.core.json; 9 | 10 | public class RedisJsonException extends RuntimeException { 11 | 12 | public RedisJsonException(String message) { 13 | super(message); 14 | } 15 | 16 | public RedisJsonException(String message, Throwable cause) { 17 | super(message, cause); 18 | } 19 | 20 | public RedisJsonException(Throwable cause) { 21 | super(cause); 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/event/jfr/NoOpEventRecorder.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.event.jfr; 2 | 3 | import io.lettuce.core.event.Event; 4 | 5 | /** 6 | * No-op implementation. 7 | * 8 | * @author Mark Paluch 9 | * @since 6.1 10 | */ 11 | enum NoOpEventRecorder implements EventRecorder, EventRecorder.RecordableEvent { 12 | 13 | INSTANCE; 14 | 15 | @Override 16 | public void record(Event event) { 17 | 18 | } 19 | 20 | @Override 21 | public RecordableEvent start(Event event) { 22 | return this; 23 | } 24 | 25 | @Override 26 | public void record() { 27 | 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/test/resources/io/lettuce/examples/SpringTest-context.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/test/java/io/lettuce/core/sentinel/SentinelTestSettings.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.sentinel; 2 | 3 | import io.lettuce.core.RedisURI; 4 | import io.lettuce.core.TestSupport; 5 | import io.lettuce.test.settings.TestSettings; 6 | 7 | /** 8 | * @author Mark Paluch 9 | */ 10 | public abstract class SentinelTestSettings extends TestSupport { 11 | 12 | public static final RedisURI SENTINEL_URI = RedisURI.Builder.sentinel(TestSettings.host(), SentinelTestSettings.MASTER_ID) 13 | .build(); 14 | 15 | public static final String MASTER_ID = "mymaster"; 16 | 17 | private SentinelTestSettings() { 18 | } 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/UnblockType.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core; 2 | 3 | import java.nio.charset.StandardCharsets; 4 | 5 | import io.lettuce.core.protocol.ProtocolKeyword; 6 | 7 | /** 8 | * Unblock type for {@code CLIENT UNBLOCK} command. 9 | * 10 | * @author Mark Paluch 11 | * @since 5.1 12 | */ 13 | public enum UnblockType implements ProtocolKeyword { 14 | 15 | TIMEOUT, ERROR; 16 | 17 | private final byte[] bytes; 18 | 19 | UnblockType() { 20 | bytes = name().getBytes(StandardCharsets.US_ASCII); 21 | } 22 | 23 | @Override 24 | public byte[] getBytes() { 25 | return bytes; 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/test/java/io/lettuce/test/Delay.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.test; 2 | 3 | import java.time.Duration; 4 | 5 | /** 6 | * @author Mark Paluch 7 | */ 8 | public class Delay { 9 | 10 | private Delay() { 11 | } 12 | 13 | /** 14 | * Sleep for the given {@link Duration}. 15 | * 16 | * @param duration 17 | */ 18 | public static void delay(Duration duration) { 19 | 20 | try { 21 | Thread.sleep(duration.toMillis()); 22 | } catch (InterruptedException e) { 23 | Thread.currentThread().interrupt(); 24 | throw new IllegalStateException(e); 25 | } 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/output/OutputFactory.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.output; 2 | 3 | import java.util.*; 4 | 5 | /** 6 | * @author Mark Paluch 7 | */ 8 | class OutputFactory { 9 | 10 | static List newList(int capacity) { 11 | 12 | if (capacity < 1) { 13 | return Collections.emptyList(); 14 | } 15 | 16 | return new ArrayList<>(Math.max(1, capacity)); 17 | } 18 | 19 | static Set newSet(int capacity) { 20 | 21 | if (capacity < 1) { 22 | return Collections.emptySet(); 23 | } 24 | 25 | return new LinkedHashSet<>(capacity, 1); 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/resource/DefaultNettyCustomizer.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.resource; 2 | 3 | import io.netty.bootstrap.Bootstrap; 4 | import io.netty.channel.Channel; 5 | 6 | /** 7 | * Default (empty) {@link NettyCustomizer} implementation. 8 | * 9 | * @author Mark Paluch 10 | * @since 4.4 11 | */ 12 | enum DefaultNettyCustomizer implements NettyCustomizer { 13 | 14 | INSTANCE; 15 | 16 | @Override 17 | public void afterBootstrapInitialized(Bootstrap bootstrap) { 18 | // no-op 19 | } 20 | 21 | @Override 22 | public void afterChannelInitialized(Channel channel) { 23 | // no-op 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/test/java/io/lettuce/core/ScoredValueStreamingAdapter.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | import io.lettuce.core.output.ScoredValueStreamingChannel; 7 | 8 | /** 9 | * @author Mark Paluch 10 | * @since 3.0 11 | */ 12 | public class ScoredValueStreamingAdapter implements ScoredValueStreamingChannel { 13 | 14 | private List> list = new ArrayList<>(); 15 | 16 | @Override 17 | public void onValue(ScoredValue value) { 18 | list.add(value); 19 | } 20 | 21 | public List> getList() { 22 | return list; 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/main/kotlin/io/lettuce/core/api/StatefulRedisConnectionExtensions.kt: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.api 2 | 3 | import io.lettuce.core.ExperimentalLettuceCoroutinesApi 4 | import io.lettuce.core.api.coroutines.RedisCoroutinesCommands 5 | import io.lettuce.core.api.coroutines.RedisCoroutinesCommandsImpl 6 | 7 | /** 8 | * Extension for [StatefulRedisConnection] to create [RedisCoroutinesCommands] 9 | * 10 | * @author Mikhael Sokolov 11 | * @author Mark Paluch 12 | * @since 6.0 13 | */ 14 | @ExperimentalLettuceCoroutinesApi 15 | fun StatefulRedisConnection.coroutines(): RedisCoroutinesCommands = RedisCoroutinesCommandsImpl(reactive()) 16 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/cluster/pubsub/api/reactive/PubSubReactiveNodeSelection.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.cluster.pubsub.api.reactive; 2 | 3 | import io.lettuce.core.cluster.api.NodeSelectionSupport; 4 | import io.lettuce.core.pubsub.api.reactive.RedisPubSubReactiveCommands; 5 | import io.lettuce.core.pubsub.api.sync.RedisPubSubCommands; 6 | 7 | /** 8 | * Node selection with access to {@link RedisPubSubCommands}. 9 | * 10 | * @author Mark Paluch 11 | * @since 4.4 12 | */ 13 | public interface PubSubReactiveNodeSelection 14 | extends NodeSelectionSupport, NodeSelectionPubSubReactiveCommands> { 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/ConnectionId.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core; 2 | 3 | import java.net.SocketAddress; 4 | 5 | /** 6 | * Connection identifier. A connection identifier consists of the {@link #localAddress()} and the {@link #remoteAddress()}. 7 | * 8 | * @author Mark Paluch 9 | * @since 3.4 10 | */ 11 | public interface ConnectionId { 12 | 13 | /** 14 | * Returns the local address. 15 | * 16 | * @return the local address 17 | */ 18 | SocketAddress localAddress(); 19 | 20 | /** 21 | * Returns the remote address. 22 | * 23 | * @return the remote address 24 | */ 25 | SocketAddress remoteAddress(); 26 | 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/event/connection/ConnectedEvent.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.event.connection; 2 | 3 | import java.net.SocketAddress; 4 | 5 | /** 6 | * Event for a established TCP-level connection. 7 | * 8 | * @author Mark Paluch 9 | * @since 3.4 10 | */ 11 | public class ConnectedEvent extends ConnectionEventSupport { 12 | 13 | public ConnectedEvent(String redisUri, String epId, String channelId, SocketAddress local, SocketAddress remote) { 14 | super(redisUri, epId, channelId, local, remote); 15 | } 16 | 17 | public ConnectedEvent(SocketAddress local, SocketAddress remote) { 18 | super(local, remote); 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/event/connection/DisconnectedEvent.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.event.connection; 2 | 3 | import java.net.SocketAddress; 4 | 5 | /** 6 | * Event for a disconnect on TCP-level. 7 | * 8 | * @author Mark Paluch 9 | * @since 3.4 10 | */ 11 | public class DisconnectedEvent extends ConnectionEventSupport { 12 | 13 | public DisconnectedEvent(String redisUri, String epId, String channelId, SocketAddress local, SocketAddress remote) { 14 | super(redisUri, epId, channelId, local, remote); 15 | } 16 | 17 | public DisconnectedEvent(SocketAddress local, SocketAddress remote) { 18 | super(local, remote); 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/protocol/ProtocolVersion.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.protocol; 2 | 3 | /** 4 | * Versions of the native protocol supported by the driver. 5 | * 6 | * @author Mark Paluch 7 | * @since 6.0 8 | */ 9 | public enum ProtocolVersion { 10 | 11 | /** 12 | * Redis 2 to Redis 5. 13 | */ 14 | RESP2, 15 | 16 | /** 17 | * Redis 6. 18 | */ 19 | RESP3; 20 | 21 | /** 22 | * Returns the newest supported protocol version. 23 | * 24 | * @return the newest supported protocol version. 25 | */ 26 | public static ProtocolVersion newestSupported() { 27 | return RESP3; 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/dynamic/segment/CommandSegmentFactory.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.dynamic.segment; 2 | 3 | import io.lettuce.core.dynamic.CommandMethod; 4 | 5 | /** 6 | * Strategy interface to create {@link CommandSegments} for a {@link CommandMethod}. 7 | * 8 | * @author Mark Paluch 9 | * @since 5.0 10 | */ 11 | public interface CommandSegmentFactory { 12 | 13 | /** 14 | * Create {@link CommandSegments} for a {@link CommandMethod}. 15 | * 16 | * @param commandMethod must not be {@code null}. 17 | * @return the {@link CommandSegments}. 18 | */ 19 | CommandSegments createCommandSegments(CommandMethod commandMethod); 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/output/ScoredValueStreamingChannel.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.output; 2 | 3 | import io.lettuce.core.ScoredValue; 4 | 5 | /** 6 | * Streaming API for multiple Keys. You can implement this interface in order to receive a call to {@code onValue} on every 7 | * value. 8 | * 9 | * @param Value type. 10 | * @author Mark Paluch 11 | * @since 3.0 12 | */ 13 | @FunctionalInterface 14 | public interface ScoredValueStreamingChannel extends StreamingChannel { 15 | 16 | /** 17 | * Called on every incoming ScoredValue. 18 | * 19 | * @param value the scored value 20 | */ 21 | void onValue(ScoredValue value); 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/output/KeyValueStreamingChannel.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.output; 2 | 3 | /** 4 | * Streaming API for multiple keys and values (tuples). You can implement this interface in order to receive a call to 5 | * {@code onKeyValue} on every key-value. 6 | * 7 | * @param Value type. 8 | * @author Mark Paluch 9 | * @since 5.0 10 | */ 11 | @FunctionalInterface 12 | public interface KeyValueStreamingChannel extends StreamingChannel { 13 | 14 | /** 15 | * Called on every incoming key/value pair. 16 | * 17 | * @param key the key 18 | * @param value the value 19 | */ 20 | void onKeyValue(K key, V value); 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/protocol/RebindState.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2025, Redis Ltd. and Contributors 3 | * All rights reserved. 4 | * 5 | * Licensed under the MIT License. 6 | */ 7 | package io.lettuce.core.protocol; 8 | 9 | import io.lettuce.core.ClientOptions; 10 | 11 | /** 12 | * The current step of the re-bind process 13 | * 14 | * @author Tihomir Mateev 15 | * @since 7.0 16 | * @see ClientOptions#getMaintNotificationsConfig() 17 | */ 18 | public enum RebindState { 19 | /** 20 | * The re-bind has been initiated by the remote server 21 | */ 22 | STARTED, 23 | 24 | /** 25 | * The re-bind has been completed 26 | */ 27 | COMPLETED 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/event/connection/ConnectEvent.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.event.connection; 2 | 3 | import io.lettuce.core.event.Event; 4 | 5 | /** 6 | * Event to connect to Redis. 7 | * 8 | * @author Mark Paluch 9 | * @since 6.1 10 | */ 11 | public class ConnectEvent implements Event { 12 | 13 | private final String redisUri; 14 | 15 | private final String epId; 16 | 17 | public ConnectEvent(String redisUri, String epId) { 18 | this.redisUri = redisUri; 19 | this.epId = epId; 20 | } 21 | 22 | public String getRedisUri() { 23 | return redisUri; 24 | } 25 | 26 | public String getEpId() { 27 | return epId; 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/test/java/io/lettuce/core/commands/BitStringCodec.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.commands; 2 | 3 | import java.nio.ByteBuffer; 4 | 5 | import io.lettuce.core.codec.StringCodec; 6 | 7 | /** 8 | * @author Mark Paluch 9 | */ 10 | public class BitStringCodec extends StringCodec { 11 | 12 | @Override 13 | public String decodeValue(ByteBuffer bytes) { 14 | StringBuilder bits = new StringBuilder(bytes.remaining() * 8); 15 | while (bytes.remaining() > 0) { 16 | byte b = bytes.get(); 17 | for (int i = 0; i < 8; i++) { 18 | bits.append(Integer.valueOf(b >>> i & 1)); 19 | } 20 | } 21 | return bits.toString(); 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/EpollProvider.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core; 2 | 3 | /** 4 | * Wraps and provides Epoll classes. This is to protect the user from {@link ClassNotFoundException}'s caused by the absence of 5 | * the {@literal netty-transport-native-epoll} library during runtime. Internal API. 6 | * 7 | * @author Mark Paluch 8 | * @since 4.4 9 | * @deprecated Use {@link io.lettuce.core.resource.EpollProvider} instead. 10 | */ 11 | @Deprecated 12 | public class EpollProvider { 13 | 14 | /** 15 | * @return {@code true} if epoll is available. 16 | */ 17 | public static boolean isAvailable() { 18 | return io.lettuce.core.resource.EpollProvider.isAvailable(); 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/dynamic/CommandFactoryResolver.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.dynamic; 2 | 3 | /** 4 | * Strategy interface to resolve a {@link CommandFactory}. 5 | * 6 | * @since 5.0 7 | */ 8 | @FunctionalInterface 9 | interface CommandFactoryResolver { 10 | 11 | /** 12 | * Resolve a {@link CommandFactory} given a{@link DeclaredCommandMethod} and {@link RedisCommandsMetadata}. 13 | * 14 | * @param method must not be {@code null}. 15 | * @param redisCommandsMetadata must not be {@code null}. 16 | * @return the {@link CommandFactory}. 17 | */ 18 | CommandFactory resolveRedisCommandFactory(CommandMethod method, RedisCommandsMetadata redisCommandsMetadata); 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/masterreplica/MasterReplicaConnector.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.masterreplica; 2 | 3 | import java.util.concurrent.CompletableFuture; 4 | 5 | import io.lettuce.core.codec.RedisCodec; 6 | 7 | /** 8 | * Interface declaring an asynchronous connect method to connect a Master/Replica setup. 9 | * 10 | * @author Mark Paluch 11 | * @since 5.1 12 | */ 13 | interface MasterReplicaConnector { 14 | 15 | /** 16 | * Asynchronously connect to a Master/Replica setup given {@link RedisCodec}. 17 | * 18 | * @return Future that is notified about the connection progress. 19 | */ 20 | CompletableFuture> connectAsync(); 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/event/connection/ConnectionDeactivatedEvent.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.event.connection; 2 | 3 | import java.net.SocketAddress; 4 | 5 | /** 6 | * Event for a connection deactivation. 7 | * 8 | * @author Mark Paluch 9 | * @since 3.4 10 | */ 11 | public class ConnectionDeactivatedEvent extends ConnectionEventSupport { 12 | 13 | public ConnectionDeactivatedEvent(String redisUri, String epId, String channelId, SocketAddress local, 14 | SocketAddress remote) { 15 | super(redisUri, epId, channelId, local, remote); 16 | } 17 | 18 | public ConnectionDeactivatedEvent(SocketAddress local, SocketAddress remote) { 19 | super(local, remote); 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/KqueueProvider.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core; 2 | 3 | /** 4 | * Wraps and provides kqueue classes. This is to protect the user from {@link ClassNotFoundException}'s caused by the absence of 5 | * the {@literal netty-transport-native-kqueue} library during runtime. Internal API. 6 | * 7 | * @author Mark Paluch 8 | * @since 4.4 9 | * @deprecated since 6.0, use {@link io.lettuce.core.resource.KqueueProvider} instead. 10 | */ 11 | @Deprecated 12 | public class KqueueProvider { 13 | 14 | /** 15 | * @return {@code true} if kqueue is available. 16 | */ 17 | public static boolean isAvailable() { 18 | return io.lettuce.core.resource.KqueueProvider.isAvailable(); 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/test/java/io/lettuce/core/commands/transactional/HLLTxCommandIntegrationTests.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.commands.transactional; 2 | 3 | import javax.inject.Inject; 4 | 5 | import io.lettuce.core.api.StatefulRedisConnection; 6 | import io.lettuce.core.commands.HLLCommandIntegrationTests; 7 | import org.junit.jupiter.api.Tag; 8 | 9 | import static io.lettuce.TestTags.INTEGRATION_TEST; 10 | 11 | /** 12 | * @author Mark Paluch 13 | */ 14 | @Tag(INTEGRATION_TEST) 15 | class HLLTxCommandIntegrationTests extends HLLCommandIntegrationTests { 16 | 17 | @Inject 18 | HLLTxCommandIntegrationTests(StatefulRedisConnection connection) { 19 | super(TxSyncInvocationHandler.sync(connection)); 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/test/java/io/lettuce/core/commands/transactional/SetTxCommandIntegrationTests.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.commands.transactional; 2 | 3 | import javax.inject.Inject; 4 | 5 | import io.lettuce.core.api.StatefulRedisConnection; 6 | import io.lettuce.core.commands.SetCommandIntegrationTests; 7 | import org.junit.jupiter.api.Tag; 8 | 9 | import static io.lettuce.TestTags.INTEGRATION_TEST; 10 | 11 | /** 12 | * @author Mark Paluch 13 | */ 14 | @Tag(INTEGRATION_TEST) 15 | class SetTxCommandIntegrationTests extends SetCommandIntegrationTests { 16 | 17 | @Inject 18 | SetTxCommandIntegrationTests(StatefulRedisConnection connection) { 19 | super(TxSyncInvocationHandler.sync(connection)); 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/assembly/docs.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | docs 6 | 7 | zip 8 | 9 | / 10 | 11 | 12 | ${project.build.directory}/site/reference/html 13 | 14 | true 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/cluster/ReconnectEventListener.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.cluster; 2 | 3 | import io.lettuce.core.ConnectionEvents.Reconnect; 4 | import io.lettuce.core.protocol.ReconnectionListener; 5 | 6 | /** 7 | * @author Mark Paluch 8 | */ 9 | class ReconnectEventListener implements ReconnectionListener { 10 | 11 | private final ClusterEventListener clusterEventListener; 12 | 13 | public ReconnectEventListener(ClusterEventListener clusterEventListener) { 14 | this.clusterEventListener = clusterEventListener; 15 | } 16 | 17 | @Override 18 | public void onReconnectAttempt(Reconnect reconnect) { 19 | clusterEventListener.onReconnectAttempt(reconnect.getAttempt()); 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/codec/ByteBufferInputStream.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.codec; 2 | 3 | import java.io.IOException; 4 | import java.io.InputStream; 5 | import java.nio.ByteBuffer; 6 | 7 | class ByteBufferInputStream extends InputStream { 8 | 9 | private final ByteBuffer buffer; 10 | 11 | public ByteBufferInputStream(ByteBuffer b) { 12 | this.buffer = b; 13 | } 14 | 15 | @Override 16 | public int available() throws IOException { 17 | return buffer.remaining(); 18 | } 19 | 20 | @Override 21 | public int read() throws IOException { 22 | if (buffer.remaining() > 0) { 23 | return (buffer.get() & 0xFF); 24 | } 25 | return -1; 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/dynamic/CommandMethodSyntaxException.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.dynamic; 2 | 3 | /** 4 | * Exception thrown if the command syntax is invalid. 5 | * 6 | * @author Mark Paluch 7 | * @since 5.0 8 | */ 9 | @SuppressWarnings("serial") 10 | public class CommandMethodSyntaxException extends CommandCreationException { 11 | 12 | /** 13 | * Create a new {@link CommandMethodSyntaxException} given {@link CommandMethod} and a message. 14 | * 15 | * @param commandMethod must not be {@code null}. 16 | * @param msg must not be {@code null}. 17 | */ 18 | public CommandMethodSyntaxException(CommandMethod commandMethod, String msg) { 19 | super(commandMethod, msg); 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/dynamic/codec/RedisCodecResolver.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.dynamic.codec; 2 | 3 | import io.lettuce.core.codec.RedisCodec; 4 | import io.lettuce.core.dynamic.CommandMethod; 5 | 6 | /** 7 | * Strategy interface to resolve a {@link RedisCodec} for a {@link CommandMethod}. 8 | * 9 | * @author Mark Paluch 10 | * @since 5.0 11 | */ 12 | public interface RedisCodecResolver { 13 | 14 | /** 15 | * Resolve a {@link RedisCodec} for the given {@link CommandMethod}. 16 | * 17 | * @param commandMethod must not be {@code null}. 18 | * @return the resolved {@link RedisCodec} or {@code null} if not resolvable. 19 | */ 20 | RedisCodec resolve(CommandMethod commandMethod); 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/tracing/TraceContextProvider.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.tracing; 2 | 3 | import reactor.core.publisher.Mono; 4 | 5 | /** 6 | * Interface to obtain a {@link TraceContext} allowing propagation of {@link Tracer.Span} {@link TraceContext}s across threads. 7 | * 8 | * @author Mark Paluch 9 | * @since 5.1 10 | */ 11 | @FunctionalInterface 12 | public interface TraceContextProvider { 13 | 14 | /** 15 | * @return the {@link TraceContext}. 16 | */ 17 | TraceContext getTraceContext(); 18 | 19 | /** 20 | * @return the {@link TraceContext}. 21 | */ 22 | default Mono getTraceContextLater() { 23 | return Mono.justOrEmpty(getTraceContext()); 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/test/java/io/lettuce/core/commands/transactional/HashTxCommandIntegrationTests.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.commands.transactional; 2 | 3 | import javax.inject.Inject; 4 | 5 | import io.lettuce.core.api.StatefulRedisConnection; 6 | import io.lettuce.core.commands.HashCommandIntegrationTests; 7 | import org.junit.jupiter.api.Tag; 8 | 9 | import static io.lettuce.TestTags.INTEGRATION_TEST; 10 | 11 | /** 12 | * @author Mark Paluch 13 | */ 14 | @Tag(INTEGRATION_TEST) 15 | class HashTxCommandIntegrationTests extends HashCommandIntegrationTests { 16 | 17 | @Inject 18 | HashTxCommandIntegrationTests(StatefulRedisConnection connection) { 19 | super(TxSyncInvocationHandler.sync(connection)); 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/test/java/io/lettuce/core/commands/transactional/ListTxCommandIntegrationTests.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.commands.transactional; 2 | 3 | import javax.inject.Inject; 4 | 5 | import io.lettuce.core.api.StatefulRedisConnection; 6 | import io.lettuce.core.commands.ListCommandIntegrationTests; 7 | import org.junit.jupiter.api.Tag; 8 | 9 | import static io.lettuce.TestTags.INTEGRATION_TEST; 10 | 11 | /** 12 | * @author Mark Paluch 13 | */ 14 | @Tag(INTEGRATION_TEST) 15 | class ListTxCommandIntegrationTests extends ListCommandIntegrationTests { 16 | 17 | @Inject 18 | ListTxCommandIntegrationTests(StatefulRedisConnection connection) { 19 | super(TxSyncInvocationHandler.sync(connection)); 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/test/java/io/lettuce/core/commands/transactional/SortTxCommandIntegrationTests.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.commands.transactional; 2 | 3 | import javax.inject.Inject; 4 | 5 | import io.lettuce.core.api.StatefulRedisConnection; 6 | import io.lettuce.core.commands.SortCommandIntegrationTests; 7 | import org.junit.jupiter.api.Tag; 8 | 9 | import static io.lettuce.TestTags.INTEGRATION_TEST; 10 | 11 | /** 12 | * @author Mark Paluch 13 | */ 14 | @Tag(INTEGRATION_TEST) 15 | class SortTxCommandIntegrationTests extends SortCommandIntegrationTests { 16 | 17 | @Inject 18 | SortTxCommandIntegrationTests(StatefulRedisConnection connection) { 19 | super(TxSyncInvocationHandler.sync(connection)); 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/ConnectionPoint.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core; 2 | 3 | /** 4 | * Interface for a connection point described with a host and port or socket. 5 | * 6 | * @author Mark Paluch 7 | */ 8 | public interface ConnectionPoint { 9 | 10 | /** 11 | * Returns the host that should represent the hostname or IPv4/IPv6 literal. 12 | * 13 | * @return the hostname/IP address 14 | */ 15 | String getHost(); 16 | 17 | /** 18 | * Get the current port number. 19 | * 20 | * @return the port number 21 | */ 22 | int getPort(); 23 | 24 | /** 25 | * Get the socket path. 26 | * 27 | * @return path to a Unix Domain Socket 28 | */ 29 | String getSocket(); 30 | 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/cluster/event/TopologyRefreshEvent.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.cluster.event; 2 | 3 | import java.util.List; 4 | 5 | import io.lettuce.core.RedisURI; 6 | import io.lettuce.core.event.Event; 7 | 8 | /** 9 | * Event for initiating a topology refresh. 10 | * 11 | * @author Mark Paluch 12 | * @since 6.1 13 | */ 14 | public class TopologyRefreshEvent implements Event { 15 | 16 | private final List topologyRefreshSource; 17 | 18 | public TopologyRefreshEvent(List topologyRefreshSource) { 19 | this.topologyRefreshSource = topologyRefreshSource; 20 | } 21 | 22 | public List getTopologyRefreshSource() { 23 | return topologyRefreshSource; 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/masterreplica/NoOpPushHandler.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.masterreplica; 2 | 3 | import java.util.Collection; 4 | import java.util.Collections; 5 | 6 | import io.lettuce.core.api.push.PushListener; 7 | import io.lettuce.core.protocol.PushHandler; 8 | 9 | /** 10 | * @author Mark Paluch 11 | */ 12 | enum NoOpPushHandler implements PushHandler { 13 | 14 | INSTANCE; 15 | 16 | @Override 17 | public void addListener(PushListener listener) { 18 | 19 | } 20 | 21 | @Override 22 | public void removeListener(PushListener listener) { 23 | 24 | } 25 | 26 | @Override 27 | public Collection getPushListeners() { 28 | return Collections.emptyList(); 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /src/main/kotlin/io/lettuce/core/cluster/api/StatefulRedisClusterConnectionExtensions.kt: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.cluster.api 2 | 3 | import io.lettuce.core.ExperimentalLettuceCoroutinesApi 4 | import io.lettuce.core.cluster.api.coroutines.RedisClusterCoroutinesCommands 5 | import io.lettuce.core.cluster.api.coroutines.RedisClusterCoroutinesCommandsImpl 6 | 7 | /** 8 | * Extension for [StatefulRedisClusterConnection] to create [RedisClusterCoroutinesCommands] 9 | * 10 | * @author Mikhael Sokolov 11 | * @author Mark Paluch 12 | * @since 6.0 13 | */ 14 | @ExperimentalLettuceCoroutinesApi 15 | fun StatefulRedisClusterConnection.coroutines(): RedisClusterCoroutinesCommands = RedisClusterCoroutinesCommandsImpl(reactive()) 16 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 4 | Make sure that: 5 | 6 | - [ ] You have read the [contribution guidelines](https://github.com/lettuce-io/lettuce-core/blob/main/.github/CONTRIBUTING.md). 7 | - [ ] You have created a feature request first to discuss your contribution intent. Please reference the feature request ticket number in the pull request. 8 | - [ ] You applied code formatting rules using the `mvn formatter:format` target. Don’t submit any formatting related changes. 9 | - [ ] You submit test cases (unit or integration tests) that back your changes. 10 | 11 | 14 | -------------------------------------------------------------------------------- /src/test/java/io/lettuce/core/commands/transactional/StringTxCommandIntegrationTests.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.commands.transactional; 2 | 3 | import javax.inject.Inject; 4 | 5 | import io.lettuce.core.api.StatefulRedisConnection; 6 | import io.lettuce.core.commands.StringCommandIntegrationTests; 7 | import org.junit.jupiter.api.Tag; 8 | 9 | import static io.lettuce.TestTags.INTEGRATION_TEST; 10 | 11 | /** 12 | * @author Mark Paluch 13 | */ 14 | @Tag(INTEGRATION_TEST) 15 | class StringTxCommandIntegrationTests extends StringCommandIntegrationTests { 16 | 17 | @Inject 18 | StringTxCommandIntegrationTests(StatefulRedisConnection connection) { 19 | super(TxSyncInvocationHandler.sync(connection)); 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/protocol/ReconnectionListener.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.protocol; 2 | 3 | import io.lettuce.core.ConnectionEvents; 4 | 5 | /** 6 | * Listener for reconnection events. 7 | * 8 | * @author Mark Paluch 9 | * @since 4.2 10 | */ 11 | public interface ReconnectionListener { 12 | 13 | ReconnectionListener NO_OP = new ReconnectionListener() { 14 | 15 | @Override 16 | public void onReconnectAttempt(ConnectionEvents.Reconnect reconnect) { 17 | 18 | } 19 | 20 | }; 21 | 22 | /** 23 | * Listener method notified on a reconnection attempt. 24 | * 25 | * @param reconnect the event payload. 26 | */ 27 | void onReconnectAttempt(ConnectionEvents.Reconnect reconnect); 28 | 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/dynamic/ExecutableCommand.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.dynamic; 2 | 3 | import java.util.concurrent.ExecutionException; 4 | 5 | /** 6 | * An executable command that can be executed calling {@link #execute(Object[])}. 7 | * 8 | * @author Mark Paluch 9 | * @since 5.0 10 | */ 11 | interface ExecutableCommand { 12 | 13 | /** 14 | * Executes the {@link ExecutableCommand} with the given parameters. 15 | * 16 | * @param parameters 17 | * @return 18 | */ 19 | Object execute(Object[] parameters) throws ExecutionException, InterruptedException; 20 | 21 | /** 22 | * Returns the {@link CommandMethod}. 23 | * 24 | * @return 25 | */ 26 | CommandMethod getCommandMethod(); 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/main/kotlin/io/lettuce/core/sentinel/api/StatefulRedisSentinelConnectionExtensions.kt: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.sentinel.api 2 | 3 | import io.lettuce.core.ExperimentalLettuceCoroutinesApi 4 | import io.lettuce.core.sentinel.api.coroutines.RedisSentinelCoroutinesCommands 5 | import io.lettuce.core.sentinel.api.coroutines.RedisSentinelCoroutinesCommandsImpl 6 | 7 | /** 8 | * Extension for [StatefulRedisSentinelConnection] to create [RedisSentinelCoroutinesCommands] 9 | * 10 | * @author Mikhael Sokolov 11 | * @author Mark Paluch 12 | * @since 6.0 13 | */ 14 | @ExperimentalLettuceCoroutinesApi 15 | fun StatefulRedisSentinelConnection.coroutines(): RedisSentinelCoroutinesCommands = RedisSentinelCoroutinesCommandsImpl(reactive()) 16 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/event/EventBus.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.event; 2 | 3 | import reactor.core.publisher.Flux; 4 | 5 | /** 6 | * Interface for an EventBus. Events can be published over the bus that are delivered to the subscribers. 7 | * 8 | * @author Mark Paluch 9 | * @since 3.4 10 | */ 11 | public interface EventBus { 12 | 13 | /** 14 | * Subscribe to the event bus and {@link Event}s. The {@link Flux} drops events on backpressure to avoid contention. 15 | * 16 | * @return the observable to obtain events. 17 | */ 18 | Flux get(); 19 | 20 | /** 21 | * Publish a {@link Event} to the bus. 22 | * 23 | * @param event the event to publish 24 | */ 25 | void publish(Event event); 26 | 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/protocol/TransactionalCommand.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.protocol; 2 | 3 | /** 4 | * A wrapper for commands within a {@literal MULTI} transaction. Commands triggered within a transaction will be completed 5 | * twice. Once on the submission and once during {@literal EXEC}. Only the second completion will complete the underlying 6 | * command. 7 | * 8 | * 9 | * @param Key type. 10 | * @param Value type. 11 | * @param Command output type. 12 | * 13 | * @author Mark Paluch 14 | */ 15 | public class TransactionalCommand extends AsyncCommand implements RedisCommand { 16 | 17 | public TransactionalCommand(RedisCommand command) { 18 | super(command, 2); 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/test/java/io/lettuce/core/commands/transactional/SortedSetTxCommandIntegrationTests.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.commands.transactional; 2 | 3 | import javax.inject.Inject; 4 | 5 | import io.lettuce.core.api.StatefulRedisConnection; 6 | import io.lettuce.core.commands.SortedSetCommandIntegrationTests; 7 | import org.junit.jupiter.api.Tag; 8 | 9 | import static io.lettuce.TestTags.INTEGRATION_TEST; 10 | 11 | /** 12 | * @author Mark Paluch 13 | */ 14 | @Tag(INTEGRATION_TEST) 15 | class SortedSetTxCommandIntegrationTests extends SortedSetCommandIntegrationTests { 16 | 17 | @Inject 18 | SortedSetTxCommandIntegrationTests(StatefulRedisConnection connection) { 19 | super(TxSyncInvocationHandler.sync(connection)); 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/dynamic/CommandFactory.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.dynamic; 2 | 3 | import io.lettuce.core.protocol.RedisCommand; 4 | 5 | /** 6 | * Strategy interface to create {@link RedisCommand}s. 7 | *

8 | * Implementing classes are required to construct {@link RedisCommand}s given an array of parameters for command execution. 9 | * 10 | * @author Mark Paluch 11 | * @since 5.0 12 | */ 13 | @FunctionalInterface 14 | interface CommandFactory { 15 | 16 | /** 17 | * Create a new {@link RedisCommand} given {@code parameters}. 18 | * 19 | * @param parameters must not be {@code null}. 20 | * @return the {@link RedisCommand}. 21 | */ 22 | RedisCommand createCommand(Object[] parameters); 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/event/metrics/MetricEventPublisher.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.event.metrics; 2 | 3 | import io.lettuce.core.event.Event; 4 | 5 | /** 6 | * Event publisher which publishes metrics by the use of {@link Event events}. 7 | * 8 | * @author Mark Paluch 9 | * @since 3.4 10 | */ 11 | public interface MetricEventPublisher { 12 | 13 | /** 14 | * Emit immediately a metrics event. 15 | */ 16 | void emitMetricsEvent(); 17 | 18 | /** 19 | * Returns {@code true} if the metric collector is enabled. 20 | * 21 | * @return {@code true} if the metric collector is enabled 22 | */ 23 | boolean isEnabled(); 24 | 25 | /** 26 | * Shut down the event publisher. 27 | */ 28 | void shutdown(); 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/test/java/io/lettuce/core/tracing/TestConfig.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.tracing; 2 | 3 | import io.micrometer.core.instrument.MeterRegistry; 4 | import io.micrometer.core.instrument.observation.DefaultMeterObservationHandler; 5 | import io.micrometer.core.instrument.simple.SimpleMeterRegistry; 6 | import io.micrometer.observation.ObservationRegistry; 7 | 8 | /** 9 | * @author Mark Paluch 10 | */ 11 | class TestConfig { 12 | 13 | static final MeterRegistry METER_REGISTRY = new SimpleMeterRegistry(); 14 | 15 | static final ObservationRegistry OBSERVATION_REGISTRY = ObservationRegistry.create(); 16 | 17 | static { 18 | OBSERVATION_REGISTRY.observationConfig().observationHandler(new DefaultMeterObservationHandler(METER_REGISTRY)); 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/output/KeyScanOutput.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.output; 2 | 3 | import java.nio.ByteBuffer; 4 | 5 | import io.lettuce.core.KeyScanCursor; 6 | import io.lettuce.core.codec.RedisCodec; 7 | 8 | /** 9 | * {@link io.lettuce.core.KeyScanCursor} for scan cursor output. 10 | * 11 | * @param Key type. 12 | * @param Value type. 13 | * @author Mark Paluch 14 | */ 15 | public class KeyScanOutput extends ScanOutput> { 16 | 17 | public KeyScanOutput(RedisCodec codec) { 18 | super(codec, new KeyScanCursor()); 19 | } 20 | 21 | @Override 22 | protected void setOutput(ByteBuffer bytes) { 23 | output.getKeys().add(bytes == null ? null : codec.decodeKey(bytes)); 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/output/ValueScanOutput.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.output; 2 | 3 | import java.nio.ByteBuffer; 4 | 5 | import io.lettuce.core.ValueScanCursor; 6 | import io.lettuce.core.codec.RedisCodec; 7 | 8 | /** 9 | * {@link io.lettuce.core.ValueScanCursor} for scan cursor output. 10 | * 11 | * @param Key type. 12 | * @param Value type. 13 | * @author Mark Paluch 14 | */ 15 | public class ValueScanOutput extends ScanOutput> { 16 | 17 | public ValueScanOutput(RedisCodec codec) { 18 | super(codec, new ValueScanCursor()); 19 | } 20 | 21 | @Override 22 | protected void setOutput(ByteBuffer bytes) { 23 | output.getValues().add(bytes == null ? null : codec.decodeValue(bytes)); 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/resource/ThreadFactoryProvider.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.resource; 2 | 3 | import java.util.concurrent.ThreadFactory; 4 | 5 | /** 6 | * Interface to provide a custom {@link java.util.concurrent.ThreadFactory}. Implementations are asked through 7 | * {@link #getThreadFactory(String)} to provide a thread factory for a given pool name. 8 | * 9 | * @since 6.1.1 10 | */ 11 | @FunctionalInterface 12 | public interface ThreadFactoryProvider { 13 | 14 | /** 15 | * Return a {@link ThreadFactory} for the given {@code poolName}. 16 | * 17 | * @param poolName a descriptive pool name. Typically used as prefix for thread names. 18 | * @return the {@link ThreadFactory}. 19 | */ 20 | ThreadFactory getThreadFactory(String poolName); 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/resource/DnsResolvers.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.resource; 2 | 3 | import java.net.InetAddress; 4 | import java.net.UnknownHostException; 5 | 6 | /** 7 | * Predefined DNS resolvers. 8 | * 9 | * @author Mark Paluch 10 | * @since 4.2 11 | */ 12 | public enum DnsResolvers implements DnsResolver { 13 | 14 | /** 15 | * Non-resolving {@link DnsResolver}. Returns an empty {@link InetAddress} to indicate an unresolved address. 16 | * 17 | * @see java.net.InetSocketAddress#createUnresolved(String, int) 18 | * @since 4.4 19 | */ 20 | UNRESOLVED { 21 | 22 | @Override 23 | public InetAddress[] resolve(String host) throws UnknownHostException { 24 | return new InetAddress[0]; 25 | } 26 | 27 | }; 28 | 29 | } 30 | -------------------------------------------------------------------------------- /src/test/java/io/lettuce/core/commands/transactional/BitTxCommandIntegrationTests.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.commands.transactional; 2 | 3 | import javax.inject.Inject; 4 | 5 | import io.lettuce.core.RedisClient; 6 | import io.lettuce.core.api.StatefulRedisConnection; 7 | import io.lettuce.core.commands.BitCommandIntegrationTests; 8 | import org.junit.jupiter.api.Tag; 9 | 10 | import static io.lettuce.TestTags.INTEGRATION_TEST; 11 | 12 | /** 13 | * @author Mark Paluch 14 | */ 15 | @Tag(INTEGRATION_TEST) 16 | class BitTxCommandIntegrationTests extends BitCommandIntegrationTests { 17 | 18 | @Inject 19 | BitTxCommandIntegrationTests(RedisClient client, StatefulRedisConnection connection) { 20 | super(client, TxSyncInvocationHandler.sync(connection)); 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/cluster/api/reactive/ReactiveExecutions.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.cluster.api.reactive; 2 | 3 | import java.util.Collection; 4 | 5 | import reactor.core.publisher.Flux; 6 | import io.lettuce.core.cluster.models.partitions.RedisClusterNode; 7 | 8 | /** 9 | * Execution holder for a reactive command to be executed on multiple nodes. 10 | * 11 | * @author Mark Paluch 12 | * @since 4.4 13 | */ 14 | public interface ReactiveExecutions { 15 | 16 | /** 17 | * Return a {@link Flux} that contains a combined stream of the multi-node execution. 18 | * 19 | * @return 20 | */ 21 | Flux flux(); 22 | 23 | /** 24 | * @return collection of nodes on which the command was executed. 25 | */ 26 | Collection nodes(); 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/test/java/io/lettuce/core/commands/reactive/HLLReactiveCommandIntegrationTests.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.commands.reactive; 2 | 3 | import javax.inject.Inject; 4 | 5 | import io.lettuce.core.api.StatefulRedisConnection; 6 | import io.lettuce.core.commands.HLLCommandIntegrationTests; 7 | import io.lettuce.test.ReactiveSyncInvocationHandler; 8 | import org.junit.jupiter.api.Tag; 9 | 10 | import static io.lettuce.TestTags.INTEGRATION_TEST; 11 | 12 | /** 13 | * @author Mark Paluch 14 | */ 15 | @Tag(INTEGRATION_TEST) 16 | class HLLReactiveCommandIntegrationTests extends HLLCommandIntegrationTests { 17 | 18 | @Inject 19 | HLLReactiveCommandIntegrationTests(StatefulRedisConnection connection) { 20 | super(ReactiveSyncInvocationHandler.sync(connection)); 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/test/java/io/lettuce/core/commands/reactive/KeyReactiveCommandIntegrationTests.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.commands.reactive; 2 | 3 | import javax.inject.Inject; 4 | 5 | import io.lettuce.core.api.StatefulRedisConnection; 6 | import io.lettuce.core.commands.KeyCommandIntegrationTests; 7 | import io.lettuce.test.ReactiveSyncInvocationHandler; 8 | import org.junit.jupiter.api.Tag; 9 | 10 | import static io.lettuce.TestTags.INTEGRATION_TEST; 11 | 12 | /** 13 | * @author Mark Paluch 14 | */ 15 | @Tag(INTEGRATION_TEST) 16 | class KeyReactiveCommandIntegrationTests extends KeyCommandIntegrationTests { 17 | 18 | @Inject 19 | KeyReactiveCommandIntegrationTests(StatefulRedisConnection connection) { 20 | super(ReactiveSyncInvocationHandler.sync(connection)); 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/test/java/io/lettuce/core/commands/reactive/SetReactiveCommandIntegrationTests.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.commands.reactive; 2 | 3 | import javax.inject.Inject; 4 | 5 | import io.lettuce.core.api.StatefulRedisConnection; 6 | import io.lettuce.core.commands.SetCommandIntegrationTests; 7 | import io.lettuce.test.ReactiveSyncInvocationHandler; 8 | import org.junit.jupiter.api.Tag; 9 | 10 | import static io.lettuce.TestTags.INTEGRATION_TEST; 11 | 12 | /** 13 | * @author Mark Paluch 14 | */ 15 | @Tag(INTEGRATION_TEST) 16 | class SetReactiveCommandIntegrationTests extends SetCommandIntegrationTests { 17 | 18 | @Inject 19 | SetReactiveCommandIntegrationTests(StatefulRedisConnection connection) { 20 | super(ReactiveSyncInvocationHandler.sync(connection)); 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/test/java/io/lettuce/core/commands/reactive/ListReactiveCommandIntegrationTests.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.commands.reactive; 2 | 3 | import javax.inject.Inject; 4 | 5 | import io.lettuce.core.api.StatefulRedisConnection; 6 | import io.lettuce.core.commands.ListCommandIntegrationTests; 7 | import io.lettuce.test.ReactiveSyncInvocationHandler; 8 | import org.junit.jupiter.api.Tag; 9 | 10 | import static io.lettuce.TestTags.INTEGRATION_TEST; 11 | 12 | /** 13 | * @author Mark Paluch 14 | */ 15 | @Tag(INTEGRATION_TEST) 16 | class ListReactiveCommandIntegrationTests extends ListCommandIntegrationTests { 17 | 18 | @Inject 19 | ListReactiveCommandIntegrationTests(StatefulRedisConnection connection) { 20 | super(ReactiveSyncInvocationHandler.sync(connection)); 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/test/java/io/lettuce/core/commands/reactive/SortReactiveCommandIntegrationTests.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.commands.reactive; 2 | 3 | import javax.inject.Inject; 4 | 5 | import io.lettuce.core.api.StatefulRedisConnection; 6 | import io.lettuce.core.commands.SortCommandIntegrationTests; 7 | import io.lettuce.test.ReactiveSyncInvocationHandler; 8 | import org.junit.jupiter.api.Tag; 9 | 10 | import static io.lettuce.TestTags.INTEGRATION_TEST; 11 | 12 | /** 13 | * @author Mark Paluch 14 | */ 15 | @Tag(INTEGRATION_TEST) 16 | class SortReactiveCommandIntegrationTests extends SortCommandIntegrationTests { 17 | 18 | @Inject 19 | SortReactiveCommandIntegrationTests(StatefulRedisConnection connection) { 20 | super(ReactiveSyncInvocationHandler.sync(connection)); 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/masterreplica/Timeout.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.masterreplica; 2 | 3 | import java.util.concurrent.TimeUnit; 4 | 5 | /** 6 | * Value object to represent a timeout. 7 | * 8 | * @author Mark Paluch 9 | * @since 4.2 10 | */ 11 | class Timeout { 12 | 13 | private final long expiresMs; 14 | 15 | public Timeout(long timeout, TimeUnit timeUnit) { 16 | this.expiresMs = System.currentTimeMillis() + timeUnit.toMillis(timeout); 17 | } 18 | 19 | public boolean isExpired() { 20 | return expiresMs < System.currentTimeMillis(); 21 | } 22 | 23 | public long remaining() { 24 | 25 | long diff = expiresMs - System.currentTimeMillis(); 26 | if (diff > 0) { 27 | return diff; 28 | } 29 | return 0; 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/dynamic/ExecutableCommandLookupStrategy.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.dynamic; 2 | 3 | import java.lang.reflect.Method; 4 | 5 | /** 6 | * Strategy interface to resolve {@link ExecutableCommand} from a {@link Method} and {@link RedisCommandsMetadata}. 7 | * 8 | * @author Mark Paluch 9 | * @since 5.0 10 | */ 11 | @FunctionalInterface 12 | interface ExecutableCommandLookupStrategy { 13 | 14 | /** 15 | * Resolve a {@link ExecutableCommand} given the {@link Method} and {@link RedisCommandsMetadata}. 16 | * 17 | * @param method must not be {@code null}. 18 | * @param metadata must not be {@code null}. 19 | * @return the {@link ExecutableCommand}. 20 | */ 21 | ExecutableCommand resolveCommandMethod(CommandMethod method, RedisCommandsMetadata metadata); 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/event/connection/ConnectionCreatedEvent.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.event.connection; 2 | 3 | import io.lettuce.core.event.Event; 4 | 5 | /** 6 | * Event for a created connection object. Creating a connection is the first step in establishing a Redis connection. 7 | * 8 | * @author Mark Paluch 9 | * @since 6.1 10 | */ 11 | public class ConnectionCreatedEvent implements Event { 12 | 13 | private final String redisUri; 14 | 15 | private final String epId; 16 | 17 | public ConnectionCreatedEvent(String redisUri, String epId) { 18 | this.redisUri = redisUri; 19 | this.epId = epId; 20 | } 21 | 22 | public String getRedisUri() { 23 | return redisUri; 24 | } 25 | 26 | public String getEpId() { 27 | return epId; 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/protocol/ConnectionInitializer.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.protocol; 2 | 3 | import java.util.concurrent.CompletionStage; 4 | 5 | import io.netty.channel.Channel; 6 | 7 | /** 8 | * Initialize a connection to prepare it for usage. 9 | * 10 | * @author Mark Paluch 11 | * @since 6.0 12 | */ 13 | public interface ConnectionInitializer { 14 | 15 | /** 16 | * Initialize the connection for usage. This method is invoked after establishing the transport connection and before the 17 | * connection is used for user-space commands. 18 | * 19 | * @param channel the {@link Channel} to initialize. 20 | * @return the {@link CompletionStage} that completes once the channel is fully initialized. 21 | */ 22 | CompletionStage initialize(Channel channel); 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/test/java/io/lettuce/core/commands/reactive/StreamReactiveCommandIntegrationTests.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.commands.reactive; 2 | 3 | import javax.inject.Inject; 4 | 5 | import io.lettuce.core.api.StatefulRedisConnection; 6 | import io.lettuce.core.commands.StreamCommandIntegrationTests; 7 | import io.lettuce.test.ReactiveSyncInvocationHandler; 8 | import org.junit.jupiter.api.Tag; 9 | 10 | import static io.lettuce.TestTags.INTEGRATION_TEST; 11 | 12 | /** 13 | * @author Mark Paluch 14 | */ 15 | @Tag(INTEGRATION_TEST) 16 | class StreamReactiveCommandIntegrationTests extends StreamCommandIntegrationTests { 17 | 18 | @Inject 19 | StreamReactiveCommandIntegrationTests(StatefulRedisConnection connection) { 20 | super(ReactiveSyncInvocationHandler.sync(connection)); 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/protocol/ProtocolKeyword.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.protocol; 2 | 3 | /** 4 | * Interface for protocol keywords providing an encoded representation. 5 | * 6 | * @author Mark Paluch 7 | */ 8 | public interface ProtocolKeyword { 9 | 10 | /** 11 | * 12 | * @return byte[] encoded representation. 13 | */ 14 | byte[] getBytes(); 15 | 16 | /** 17 | * 18 | * @return name of the command. 19 | */ 20 | String toString(); 21 | 22 | /** 23 | * Return the keyword as a String. This method is retained for binary compatibility with existing integrations. 24 | * 25 | * @deprecated since 6.5, use {@link #toString()} instead. 26 | */ 27 | @Deprecated 28 | default String name() { 29 | return this.toString(); 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/test/java/io/lettuce/core/commands/reactive/NumericReactiveCommandIntegrationTests.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.commands.reactive; 2 | 3 | import javax.inject.Inject; 4 | 5 | import io.lettuce.core.api.StatefulRedisConnection; 6 | import io.lettuce.core.commands.NumericCommandIntegrationTests; 7 | import io.lettuce.test.ReactiveSyncInvocationHandler; 8 | import org.junit.jupiter.api.Tag; 9 | 10 | import static io.lettuce.TestTags.INTEGRATION_TEST; 11 | 12 | /** 13 | * @author Mark Paluch 14 | */ 15 | @Tag(INTEGRATION_TEST) 16 | class NumericReactiveCommandIntegrationTests extends NumericCommandIntegrationTests { 17 | 18 | @Inject 19 | NumericReactiveCommandIntegrationTests(StatefulRedisConnection connection) { 20 | super(ReactiveSyncInvocationHandler.sync(connection)); 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/protocol/ConnectionFacade.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.protocol; 2 | 3 | /** 4 | * Represents a stateful connection facade. Connections can be activated and deactivated and particular actions can be executed 5 | * upon connection activation/deactivation. 6 | * 7 | * @author Mark Paluch 8 | */ 9 | public interface ConnectionFacade { 10 | 11 | /** 12 | * Callback for a connection activated event. This method may invoke non-blocking connection operations to prepare the 13 | * connection after the connection was established. 14 | */ 15 | void activated(); 16 | 17 | /** 18 | * Callback for a connection deactivated event. This method may invoke non-blocking operations to cleanup the connection 19 | * after disconnection. 20 | */ 21 | void deactivated(); 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/test/java/io/lettuce/examples/ConnectToRedisSSL.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.examples; 2 | 3 | import io.lettuce.core.RedisClient; 4 | import io.lettuce.core.api.StatefulRedisConnection; 5 | 6 | /** 7 | * @author Mark Paluch 8 | */ 9 | public class ConnectToRedisSSL { 10 | 11 | public static void main(String[] args) { 12 | 13 | // Syntax: rediss://[password@]host[:port][/databaseNumber] 14 | // Adopt the port to the stunnel port in front of your Redis instance 15 | RedisClient redisClient = RedisClient.create("rediss://password@localhost:6443/0"); 16 | 17 | StatefulRedisConnection connection = redisClient.connect(); 18 | 19 | System.out.println("Connected to Redis using SSL"); 20 | 21 | connection.close(); 22 | redisClient.shutdown(); 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/test/java/io/lettuce/core/ScanArgsUnitTests.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core; 2 | 3 | import static io.lettuce.TestTags.UNIT_TEST; 4 | import static org.assertj.core.api.Assertions.assertThat; 5 | 6 | import org.junit.jupiter.api.Tag; 7 | import org.junit.jupiter.api.Test; 8 | 9 | import io.lettuce.core.codec.StringCodec; 10 | import io.lettuce.core.protocol.CommandArgs; 11 | 12 | /** 13 | * @author Mark Paluch 14 | */ 15 | @Tag(UNIT_TEST) 16 | class ScanArgsUnitTests { 17 | 18 | @Test 19 | void shouldEncodeMatchUsingUtf8() { 20 | 21 | ScanArgs args = ScanArgs.Builder.matches("ö"); 22 | 23 | CommandArgs commandArgs = new CommandArgs<>(StringCodec.UTF8); 24 | args.build(commandArgs); 25 | 26 | assertThat(commandArgs.toCommandString()).isEqualTo("MATCH w7Y="); 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/vector/VSimScoreAttribs.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2025, Redis Ltd. and Contributors 3 | * All rights reserved. 4 | * 5 | * Licensed under the MIT License. 6 | */ 7 | package io.lettuce.core.vector; 8 | 9 | /** 10 | * Holder for a VSIM result entry that includes both the similarity score and the element attributes when WITHATTRIBS is 11 | * requested. 12 | */ 13 | public final class VSimScoreAttribs { 14 | 15 | private final double score; 16 | 17 | private final String attributes; 18 | 19 | public VSimScoreAttribs(double score, String attributes) { 20 | this.score = score; 21 | this.attributes = attributes; 22 | } 23 | 24 | public double getScore() { 25 | return score; 26 | } 27 | 28 | public String getAttributes() { 29 | return attributes; 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/test/java/io/lettuce/examples/ConnectToRedisUsingRedisSentinel.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.examples; 2 | 3 | import io.lettuce.core.RedisClient; 4 | import io.lettuce.core.api.StatefulRedisConnection; 5 | 6 | /** 7 | * @author Mark Paluch 8 | */ 9 | public class ConnectToRedisUsingRedisSentinel { 10 | 11 | public static void main(String[] args) { 12 | 13 | // Syntax: redis-sentinel://[password@]host[:port][,host2[:port2]][/databaseNumber]#sentinelMasterId 14 | RedisClient redisClient = RedisClient.create("redis-sentinel://localhost:26379,localhost:26380/0#mymaster"); 15 | 16 | StatefulRedisConnection connection = redisClient.connect(); 17 | 18 | System.out.println("Connected to Redis using Redis Sentinel"); 19 | 20 | connection.close(); 21 | redisClient.shutdown(); 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/test/java/io/lettuce/test/condition/EnabledOnCommand.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.test.condition; 2 | 3 | import java.lang.annotation.*; 4 | 5 | import org.junit.jupiter.api.extension.ExtendWith; 6 | 7 | /** 8 | * {@code @EnabledOnCommand} is used to signal that the annotated test class or test method is only enabledif the 9 | * specified command is available. 10 | * 11 | *

12 | * When applied at the class level, all test methods within that class will be enabled . 13 | */ 14 | @Target({ ElementType.TYPE, ElementType.METHOD }) 15 | @Retention(RetentionPolicy.RUNTIME) 16 | @Inherited 17 | @Documented 18 | @ExtendWith(EnabledOnCommandCondition.class) 19 | public @interface EnabledOnCommand { 20 | 21 | /** 22 | * Name of the Redis command to be available. 23 | * 24 | * @return 25 | */ 26 | String value(); 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/masterreplica/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Client support for Redis Master/Replica setups. {@link io.lettuce.core.masterreplica.MasterReplica} supports self-managed, 3 | * Redis Sentinel-managed, AWS ElastiCache and Azure Redis managed Master/Replica setups. 4 | * 5 | * Connections can be obtained by providing the {@link io.lettuce.core.RedisClient}, a {@link io.lettuce.core.RedisURI} and a 6 | * {@link io.lettuce.core.codec.RedisCodec}. 7 | * 8 | *

 9 |  *
10 |  * RedisClient client = RedisClient.create();
11 |  * StatefulRedisMasterReplicaConnection connection = MasterReplica.connect(client,
12 |  *         RedisURI.create("redis://localhost"), StringCodec.UTF8);
13 |  * // ...
14 |  *
15 |  * connection.close();
16 |  * client.shutdown();
17 |  * 
18 | */ 19 | package io.lettuce.core.masterreplica; 20 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/support/caching/MapCacheAccessor.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.support.caching; 2 | 3 | import java.util.Map; 4 | 5 | /** 6 | * {@link CacheAccessor} implementation for {@link Map}-based cache implementations. 7 | * 8 | * @param Key type. 9 | * @param Value type. 10 | * @author Mark Paluch 11 | * @since 6.0 12 | */ 13 | class MapCacheAccessor implements CacheAccessor { 14 | 15 | private final Map map; 16 | 17 | MapCacheAccessor(Map map) { 18 | this.map = map; 19 | } 20 | 21 | @Override 22 | public V get(K key) { 23 | return map.get(key); 24 | } 25 | 26 | @Override 27 | public void put(K key, V value) { 28 | map.put(key, value); 29 | } 30 | 31 | @Override 32 | public void evict(K key) { 33 | map.remove(key); 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /src/test/java/io/lettuce/core/commands/transactional/KeyTxCommandIntegrationTests.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.commands.transactional; 2 | 3 | import javax.inject.Inject; 4 | 5 | import org.junit.jupiter.api.Disabled; 6 | 7 | import io.lettuce.core.api.StatefulRedisConnection; 8 | import io.lettuce.core.commands.KeyCommandIntegrationTests; 9 | import org.junit.jupiter.api.Tag; 10 | 11 | import static io.lettuce.TestTags.INTEGRATION_TEST; 12 | 13 | /** 14 | * @author Mark Paluch 15 | */ 16 | @Tag(INTEGRATION_TEST) 17 | public class KeyTxCommandIntegrationTests extends KeyCommandIntegrationTests { 18 | 19 | @Inject 20 | KeyTxCommandIntegrationTests(StatefulRedisConnection connection) { 21 | super(TxSyncInvocationHandler.sync(connection)); 22 | } 23 | 24 | @Disabled 25 | @Override 26 | public void move() { 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/CloseEvents.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core; 2 | 3 | import java.util.Set; 4 | import java.util.concurrent.ConcurrentHashMap; 5 | 6 | /** 7 | * Close Events Facility. Can register/unregister CloseListener and fire a closed event to all registered listeners. 8 | * 9 | * @author Mark Paluch 10 | * @since 3.0 11 | */ 12 | class CloseEvents { 13 | 14 | private final Set listeners = ConcurrentHashMap.newKeySet(); 15 | 16 | public void fireEventClosed(Object resource) { 17 | for (CloseListener listener : listeners) { 18 | listener.resourceClosed(resource); 19 | } 20 | } 21 | 22 | public void addListener(CloseListener listener) { 23 | listeners.add(listener); 24 | } 25 | 26 | interface CloseListener { 27 | 28 | void resourceClosed(Object resource); 29 | 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/event/connection/ConnectionActivatedEvent.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.event.connection; 2 | 3 | import java.net.SocketAddress; 4 | 5 | import io.lettuce.core.ClientOptions; 6 | 7 | /** 8 | * Event for a connection activation (after SSL-handshake, {@link ClientOptions#isPingBeforeActivateConnection() PING before 9 | * activation}, and buffered command replay). 10 | * 11 | * @author Mark Paluch 12 | * @since 3.4 13 | */ 14 | public class ConnectionActivatedEvent extends ConnectionEventSupport { 15 | 16 | public ConnectionActivatedEvent(String redisUri, String epId, String channelId, SocketAddress local, SocketAddress remote) { 17 | super(redisUri, epId, channelId, local, remote); 18 | } 19 | 20 | public ConnectionActivatedEvent(SocketAddress local, SocketAddress remote) { 21 | super(local, remote); 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/api/AsyncCloseable.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.api; 2 | 3 | import java.util.concurrent.CompletableFuture; 4 | 5 | /** 6 | * A {@link AsyncCloseable} is a resource that can be closed. The {@link #closeAsync()} method is invoked to request resources 7 | * release that the object is holding (such as open files). 8 | * 9 | * @since 6.2 10 | * @author Mark Paluch 11 | */ 12 | public interface AsyncCloseable extends io.lettuce.core.internal.AsyncCloseable { 13 | 14 | /** 15 | * Requests to close this object and releases any system resources associated with it. If the object is already closed then 16 | * invoking this method has no effect. 17 | *

18 | * Calls to this method return a {@link CompletableFuture} that is notified with the outcome of the close request. 19 | */ 20 | CompletableFuture closeAsync(); 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/pubsub/api/reactive/ChannelMessage.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.pubsub.api.reactive; 2 | 3 | /** 4 | * Message payload for a subscription to a channel. 5 | * 6 | * @author Mark Paluch 7 | */ 8 | public class ChannelMessage { 9 | 10 | private final K channel; 11 | 12 | private final V message; 13 | 14 | /** 15 | * 16 | * @param channel the channel 17 | * @param message the message 18 | */ 19 | public ChannelMessage(K channel, V message) { 20 | this.channel = channel; 21 | this.message = message; 22 | } 23 | 24 | /** 25 | * 26 | * @return the channel 27 | */ 28 | public K getChannel() { 29 | return channel; 30 | } 31 | 32 | /** 33 | * 34 | * @return the message 35 | */ 36 | public V getMessage() { 37 | return message; 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /src/test/java/io/lettuce/test/RoutingInvocationHandler.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.test; 2 | 3 | import java.lang.reflect.InvocationHandler; 4 | import java.lang.reflect.Method; 5 | 6 | /** 7 | * @author Mark Paluch 8 | */ 9 | public class RoutingInvocationHandler extends ConnectionDecoratingInvocationHandler { 10 | 11 | private final InvocationHandler delegate; 12 | 13 | public RoutingInvocationHandler(Object target, InvocationHandler delegate) { 14 | super(target); 15 | this.delegate = delegate; 16 | } 17 | 18 | @Override 19 | protected Object handleInvocation(Object proxy, Method method, Object[] args) throws Throwable { 20 | 21 | if (method.getName().equals("getStatefulConnection")) { 22 | return super.handleInvocation(proxy, method, args); 23 | } 24 | 25 | return delegate.invoke(proxy, method, args); 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /.github/workflows/release-drafter.yml: -------------------------------------------------------------------------------- 1 | name: Release Drafter 2 | 3 | on: workflow_dispatch 4 | 5 | permissions: 6 | contents: read 7 | 8 | jobs: 9 | update_release_draft: 10 | permissions: 11 | # write permission is required to create a github release 12 | contents: write 13 | # write permission is required for autolabeler 14 | # otherwise, read permission is required at least 15 | pull-requests: write 16 | runs-on: ubuntu-latest 17 | steps: 18 | # Drafts your next Release notes as Pull Requests are merged into "master" 19 | - uses: release-drafter/release-drafter@v6 20 | with: 21 | # (Optional) specify config name to use, relative to .github/. Default: release-drafter.yml 22 | config-name: release-drafter-config.yml 23 | commitish: main 24 | env: 25 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 26 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/protocol/ActivationCommand.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.protocol; 2 | 3 | /** 4 | * Command wrapper to identify activation commands. 5 | * 6 | * @author Mark Paluch 7 | */ 8 | class ActivationCommand extends CommandWrapper { 9 | 10 | public ActivationCommand(RedisCommand command) { 11 | super(command); 12 | } 13 | 14 | public static boolean isActivationCommand(RedisCommand command) { 15 | 16 | if (command instanceof ActivationCommand) { 17 | return true; 18 | } 19 | 20 | while (command instanceof CommandWrapper) { 21 | command = ((CommandWrapper) command).getDelegate(); 22 | 23 | if (command instanceof ActivationCommand) { 24 | return true; 25 | } 26 | } 27 | 28 | return false; 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /src/test/java/io/lettuce/core/commands/reactive/FunctionReactiveCommandIntegrationTests.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.commands.reactive; 2 | 3 | import javax.inject.Inject; 4 | 5 | import io.lettuce.core.RedisClient; 6 | import io.lettuce.core.api.StatefulRedisConnection; 7 | import io.lettuce.core.commands.FunctionCommandIntegrationTests; 8 | import io.lettuce.test.ReactiveSyncInvocationHandler; 9 | import org.junit.jupiter.api.Tag; 10 | 11 | import static io.lettuce.TestTags.INTEGRATION_TEST; 12 | 13 | /** 14 | * @author Mark Paluch 15 | */ 16 | @Tag(INTEGRATION_TEST) 17 | class FunctionReactiveCommandIntegrationTests extends FunctionCommandIntegrationTests { 18 | 19 | @Inject 20 | FunctionReactiveCommandIntegrationTests(RedisClient client, StatefulRedisConnection connection) { 21 | super(client, ReactiveSyncInvocationHandler.sync(connection)); 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/RedisConnectionStateAdapter.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core; 2 | 3 | import java.net.SocketAddress; 4 | 5 | /** 6 | * Convenience adapter with an empty implementation of all {@link RedisConnectionStateListener} callback methods. 7 | * 8 | * @author Mark Paluch 9 | * @since 4.4 10 | */ 11 | public class RedisConnectionStateAdapter implements RedisConnectionStateListener { 12 | 13 | @Override 14 | public void onRedisConnected(RedisChannelHandler connection, SocketAddress socketAddress) { 15 | // empty adapter method 16 | } 17 | 18 | @Override 19 | public void onRedisDisconnected(RedisChannelHandler connection) { 20 | // empty adapter method 21 | } 22 | 23 | @Override 24 | public void onRedisExceptionCaught(RedisChannelHandler connection, Throwable cause) { 25 | // empty adapter method 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/cluster/api/push/RedisClusterPushListener.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.cluster.api.push; 2 | 3 | import io.lettuce.core.api.push.PushMessage; 4 | import io.lettuce.core.cluster.models.partitions.RedisClusterNode; 5 | 6 | /** 7 | * Interface to be implemented by push message listeners that are interested in listening to {@link PushMessage} using Redis 8 | * Cluster. 9 | * 10 | * @author Mark Paluch 11 | * @since 6.0 12 | * @see PushMessage 13 | * @see io.lettuce.core.api.push.PushListener 14 | */ 15 | @FunctionalInterface 16 | public interface RedisClusterPushListener { 17 | 18 | /** 19 | * Handle a push message. 20 | * 21 | * @param node the {@link RedisClusterNode} from which the {@code message} originates. 22 | * @param message message to respond to. 23 | */ 24 | void onPushMessage(RedisClusterNode node, PushMessage message); 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/dynamic/output/CommandOutputFactory.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.dynamic.output; 2 | 3 | import io.lettuce.core.codec.RedisCodec; 4 | import io.lettuce.core.output.CommandOutput; 5 | 6 | /** 7 | * Strategy interface to create {@link CommandOutput} given {@link RedisCodec}. 8 | * 9 | *

10 | * Implementing classes usually produce the same {@link CommandOutput} type. 11 | * 12 | * @author Mark Paluch 13 | * @since 5.0 14 | */ 15 | @FunctionalInterface 16 | public interface CommandOutputFactory { 17 | 18 | /** 19 | * Create and initialize a new {@link CommandOutput} given {@link RedisCodec}. 20 | * 21 | * @param codec must not be {@code null}. 22 | * @param Key type. 23 | * @param Value type. 24 | * @return the new {@link CommandOutput}. 25 | */ 26 | CommandOutput create(RedisCodec codec); 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/output/KeyStreamingOutput.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.output; 2 | 3 | import java.nio.ByteBuffer; 4 | 5 | import io.lettuce.core.codec.RedisCodec; 6 | 7 | /** 8 | * Streaming-Output of Keys. Returns the count of all keys (including null). 9 | * 10 | * @param Key type. 11 | * @param Value type. 12 | * @author Mark Paluch 13 | */ 14 | public class KeyStreamingOutput extends CommandOutput { 15 | 16 | private final KeyStreamingChannel channel; 17 | 18 | public KeyStreamingOutput(RedisCodec codec, KeyStreamingChannel channel) { 19 | super(codec, Long.valueOf(0)); 20 | this.channel = channel; 21 | } 22 | 23 | @Override 24 | public void set(ByteBuffer bytes) { 25 | 26 | channel.onKey(bytes == null ? null : codec.decodeKey(bytes)); 27 | output = output.longValue() + 1; 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/test/java/io/lettuce/core/commands/reactive/AclReactiveCommandIntegrationTests.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.commands.reactive; 2 | 3 | import javax.inject.Inject; 4 | 5 | import io.lettuce.core.api.StatefulRedisConnection; 6 | import io.lettuce.core.commands.AclCommandIntegrationTests; 7 | import io.lettuce.test.ReactiveSyncInvocationHandler; 8 | import org.junit.jupiter.api.Tag; 9 | 10 | import static io.lettuce.TestTags.INTEGRATION_TEST; 11 | 12 | /** 13 | * Integration tests though the reactive facade for {@link AclCommandIntegrationTests}. 14 | * 15 | * @author Mark Paluch 16 | */ 17 | @Tag(INTEGRATION_TEST) 18 | class AclReactiveCommandIntegrationTests extends AclCommandIntegrationTests { 19 | 20 | @Inject 21 | AclReactiveCommandIntegrationTests(StatefulRedisConnection connection) { 22 | super(ReactiveSyncInvocationHandler.sync(connection)); 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/test/java/io/lettuce/core/commands/reactive/ScriptingReactiveCommandIntegrationTests.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.commands.reactive; 2 | 3 | import javax.inject.Inject; 4 | 5 | import io.lettuce.core.RedisClient; 6 | import io.lettuce.core.api.StatefulRedisConnection; 7 | import io.lettuce.core.commands.ScriptingCommandIntegrationTests; 8 | import io.lettuce.test.ReactiveSyncInvocationHandler; 9 | import org.junit.jupiter.api.Tag; 10 | 11 | import static io.lettuce.TestTags.INTEGRATION_TEST; 12 | 13 | /** 14 | * @author Mark Paluch 15 | */ 16 | @Tag(INTEGRATION_TEST) 17 | class ScriptingReactiveCommandIntegrationTests extends ScriptingCommandIntegrationTests { 18 | 19 | @Inject 20 | ScriptingReactiveCommandIntegrationTests(RedisClient client, StatefulRedisConnection connection) { 21 | super(client, ReactiveSyncInvocationHandler.sync(connection)); 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/dynamic/batch/BatchExecutor.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.dynamic.batch; 2 | 3 | /** 4 | * Batch executor interface to enforce command queue flushing using {@link BatchSize}. 5 | *

6 | * Commands remain in a batch queue until the batch size is reached or the queue is {@link BatchExecutor#flush() flushed}. If 7 | * the batch size is not reached, commands remain not executed. 8 | *

9 | * Commands that fail during the batch cause a {@link BatchException} while non-failed commands remain executed successfully. 10 | * 11 | * @author Mark Paluch 12 | * @since 5.0 13 | * @see BatchSize 14 | */ 15 | public interface BatchExecutor { 16 | 17 | /** 18 | * Flush the command queue resulting in the queued commands being executed. 19 | * 20 | * @throws BatchException if at least one command failed. 21 | */ 22 | void flush() throws BatchException; 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/event/connection/JfrConnectionCreatedEvent.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.event.connection; 2 | 3 | import jdk.jfr.Category; 4 | import jdk.jfr.Event; 5 | import jdk.jfr.Label; 6 | 7 | /** 8 | * Flight recorder event variant of {@link ConnectionCreatedEvent}. 9 | * 10 | * @author Mark Paluch 11 | * @since 6.1 12 | */ 13 | @Category({ "Lettuce", "Connection Events" }) 14 | @Label("Connection Created") 15 | class JfrConnectionCreatedEvent extends Event { 16 | 17 | private final String redisUri; 18 | 19 | private final String epId; 20 | 21 | public JfrConnectionCreatedEvent(ConnectionCreatedEvent event) { 22 | this.redisUri = event.getRedisUri(); 23 | this.epId = event.getEpId(); 24 | } 25 | 26 | public String getRedisUri() { 27 | return redisUri; 28 | } 29 | 30 | public String getEpId() { 31 | return epId; 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/pubsub/PubSubCommandArgs.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.pubsub; 2 | 3 | import java.nio.ByteBuffer; 4 | 5 | import io.lettuce.core.codec.RedisCodec; 6 | import io.lettuce.core.protocol.CommandArgs; 7 | 8 | /** 9 | * 10 | * Command args for Pub/Sub connections. This implementation hides the first key as PubSub keys are not keys from the key-space. 11 | * 12 | * @author Mark Paluch 13 | * @since 4.2 14 | */ 15 | class PubSubCommandArgs extends CommandArgs { 16 | 17 | /** 18 | * @param codec Codec used to encode/decode keys and values, must not be {@code null}. 19 | */ 20 | public PubSubCommandArgs(RedisCodec codec) { 21 | super(codec); 22 | } 23 | 24 | /** 25 | * 26 | * @return always {@code null}. 27 | */ 28 | @Override 29 | public ByteBuffer getFirstEncodedKey() { 30 | return null; 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/pubsub/PubSubMessage.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.pubsub; 2 | 3 | /** 4 | * Represents a Pub/Sub notification message. 5 | * 6 | * @author Mark Paluch 7 | * @since 6.0 8 | */ 9 | public interface PubSubMessage { 10 | 11 | /** 12 | * @return the {@link PubSubOutput.Type} message type. 13 | */ 14 | PubSubOutput.Type type(); 15 | 16 | /** 17 | * @return name of the channel to which this notification belongs to. 18 | */ 19 | K channel(); 20 | 21 | /** 22 | * @return pattern that applies if the message was received through a pattern subscription. Can be {@code null}. 23 | */ 24 | K pattern(); 25 | 26 | /** 27 | * @return the subscriber count if applicable. 28 | */ 29 | long count(); 30 | 31 | /** 32 | * @return the message body, if applicable. Can be {@code null}. 33 | */ 34 | V body(); 35 | 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/output/ComplexDataParser.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2024, Redis Ltd. and Contributors 3 | * All rights reserved. 4 | * 5 | * Licensed under the MIT License. 6 | */ 7 | 8 | package io.lettuce.core.output; 9 | 10 | /** 11 | * Any usage of the {@link ComplexOutput} comes hand in hand with a respective {@link ComplexDataParser} that is able to parse 12 | * the data extracted from the server to a meaningful Java object. 13 | * 14 | * @param the type of the parsed object 15 | * @author Tihomir Mateev 16 | * @see ComplexData 17 | * @see ComplexOutput 18 | * @since 6.5 19 | */ 20 | public interface ComplexDataParser { 21 | 22 | /** 23 | * Parse the data extracted from the server to a specific domain object. 24 | * 25 | * @param data the data to parse 26 | * @return the parsed object 27 | * @since 6.5 28 | */ 29 | T parse(ComplexData data); 30 | 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/output/ValueStreamingOutput.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.output; 2 | 3 | import java.nio.ByteBuffer; 4 | 5 | import io.lettuce.core.codec.RedisCodec; 6 | 7 | /** 8 | * Streaming-Output of Values. Returns the count of all values (including null). 9 | * 10 | * @param Key type. 11 | * @param Value type. 12 | * @author Mark Paluch 13 | */ 14 | public class ValueStreamingOutput extends CommandOutput { 15 | 16 | private final ValueStreamingChannel channel; 17 | 18 | public ValueStreamingOutput(RedisCodec codec, ValueStreamingChannel channel) { 19 | super(codec, Long.valueOf(0)); 20 | this.channel = channel; 21 | } 22 | 23 | @Override 24 | public void set(ByteBuffer bytes) { 25 | 26 | channel.onValue(bytes == null ? null : codec.decodeValue(bytes)); 27 | output = output.longValue() + 1; 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/tracing/LettuceObservationConvention.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.tracing; 2 | 3 | import io.micrometer.observation.Observation; 4 | import io.micrometer.observation.ObservationConvention; 5 | 6 | /** 7 | * {@link ObservationConvention} for {@link LettuceObservationContext}. 8 | * 9 | * @author Mark Paluch 10 | * @since 6.3 11 | */ 12 | public interface LettuceObservationConvention extends ObservationConvention { 13 | 14 | @Override 15 | default boolean supportsContext(Observation.Context context) { 16 | return context instanceof LettuceObservationContext; 17 | } 18 | 19 | /** 20 | * @return whether to attach the full command into the trace. Use this flag with caution as sensitive arguments will be 21 | * captured in the observation spans and metric tags. 22 | */ 23 | boolean includeCommandArgsInSpanTags(); 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/test/java/io/lettuce/core/TestRedisPublisher.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core; 2 | 3 | import java.util.function.Supplier; 4 | 5 | import io.lettuce.core.api.StatefulConnection; 6 | import io.lettuce.core.protocol.RedisCommand; 7 | import io.netty.util.concurrent.ImmediateEventExecutor; 8 | 9 | /** 10 | * @author Mark Paluch 11 | */ 12 | public class TestRedisPublisher extends RedisPublisher { 13 | 14 | public TestRedisPublisher(RedisCommand staticCommand, StatefulConnection connection, boolean dissolve) { 15 | super(staticCommand, connection, dissolve, ImmediateEventExecutor.INSTANCE); 16 | } 17 | 18 | public TestRedisPublisher(Supplier> redisCommandSupplier, StatefulConnection connection, 19 | boolean dissolve) { 20 | super(redisCommandSupplier, connection, dissolve, ImmediateEventExecutor.INSTANCE); 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/test/java/io/lettuce/test/resource/FastShutdown.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.test.resource; 2 | 3 | import java.util.concurrent.TimeUnit; 4 | 5 | import io.lettuce.core.AbstractRedisClient; 6 | import io.lettuce.core.resource.ClientResources; 7 | 8 | /** 9 | * @author Mark Paluch 10 | */ 11 | public class FastShutdown { 12 | 13 | /** 14 | * Shut down a {@link AbstractRedisClient} with a timeout of 10ms. 15 | * 16 | * @param redisClient 17 | */ 18 | public static void shutdown(AbstractRedisClient redisClient) { 19 | redisClient.shutdown(0, 10, TimeUnit.MILLISECONDS); 20 | } 21 | 22 | /** 23 | * Shut down a {@link ClientResources} client with a timeout of 10ms. 24 | * 25 | * @param clientResources 26 | */ 27 | public static void shutdown(ClientResources clientResources) { 28 | clientResources.shutdown(0, 10, TimeUnit.MILLISECONDS); 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/event/connection/ReauthenticationEvent.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2024, Redis Ltd. and Contributors 3 | * All rights reserved. 4 | * 5 | * Licensed under the MIT License. 6 | */ 7 | package io.lettuce.core.event.connection; 8 | 9 | /** 10 | * Event fired on successful connection re-authentication 11 | * 12 | * @author Ivo Gaydajiev 13 | * @since 6.6.0 14 | * @see io.lettuce.core.RedisCredentialsProvider 15 | */ 16 | public class ReauthenticationEvent implements AuthenticationEvent { 17 | 18 | private final String epId; 19 | 20 | /** 21 | * Create a new {@link ReauthenticationEvent} given a connection endpoint ID 22 | * 23 | * @param epId the connection endpoint ID 24 | */ 25 | public ReauthenticationEvent(String epId) { 26 | this.epId = epId; 27 | } 28 | 29 | @Override 30 | public String getEpId() { 31 | return epId; 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /src/test/java/io/lettuce/core/LimitUnitTests.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core; 2 | 3 | import static io.lettuce.TestTags.UNIT_TEST; 4 | import static org.assertj.core.api.Assertions.assertThat; 5 | 6 | import org.junit.jupiter.api.Tag; 7 | import org.junit.jupiter.api.Test; 8 | 9 | /** 10 | * @author Mark Paluch 11 | */ 12 | @Tag(UNIT_TEST) 13 | class LimitUnitTests { 14 | 15 | @Test 16 | void create() { 17 | 18 | Limit limit = Limit.create(1, 2); 19 | 20 | assertThat(limit.getOffset()).isEqualTo(1); 21 | assertThat(limit.getCount()).isEqualTo(2); 22 | assertThat(limit.isLimited()).isTrue(); 23 | } 24 | 25 | @Test 26 | void unlimited() { 27 | 28 | Limit limit = Limit.unlimited(); 29 | 30 | assertThat(limit.getOffset()).isEqualTo(-1); 31 | assertThat(limit.getCount()).isEqualTo(-1); 32 | assertThat(limit.isLimited()).isFalse(); 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/masterslave/package-info.java: -------------------------------------------------------------------------------- 1 | /** 2 | * Client support for Redis Master/Slave setups. {@link io.lettuce.core.masterslave.MasterSlave} supports self-managed, Redis 3 | * Sentinel-managed, AWS ElastiCache and Azure Redis managed Master/Slave setups. 4 | * 5 | * Connections can be obtained by providing the {@link io.lettuce.core.RedisClient}, a {@link io.lettuce.core.RedisURI} and a 6 | * {@link io.lettuce.core.codec.RedisCodec}. 7 | * 8 | *

 9 |  *
10 |  * RedisClient client = RedisClient.create();
11 |  * StatefulRedisMasterSlaveConnection connection = MasterSlave.connect(client,
12 |  *         RedisURI.create("redis://localhost"), StringCodec.UTF8);
13 |  * // ...
14 |  *
15 |  * connection.close();
16 |  * client.shutdown();
17 |  * 
18 | * 19 | * @deprecated will be moved to {@code masterreplica} package with version 6. 20 | */ 21 | package io.lettuce.core.masterslave; 22 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/event/connection/JfrConnectEvent.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.event.connection; 2 | 3 | import jdk.jfr.Category; 4 | import jdk.jfr.Event; 5 | import jdk.jfr.Label; 6 | import jdk.jfr.StackTrace; 7 | 8 | /** 9 | * Flight recorder event variant of {@link ConnectionCreatedEvent}. 10 | * 11 | * @author Mark Paluch 12 | * @since 6.1 13 | */ 14 | @Category({ "Lettuce", "Connection Events" }) 15 | @Label("Connect to a Redis server") 16 | @StackTrace(value = false) 17 | class JfrConnectEvent extends Event { 18 | 19 | private final String redisUri; 20 | 21 | private final String epId; 22 | 23 | public JfrConnectEvent(ConnectEvent event) { 24 | this.redisUri = event.getRedisUri(); 25 | this.epId = event.getEpId(); 26 | } 27 | 28 | public String getRedisUri() { 29 | return redisUri; 30 | } 31 | 32 | public String getEpId() { 33 | return epId; 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/internal/AsyncCloseable.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.internal; 2 | 3 | import java.util.concurrent.CompletableFuture; 4 | 5 | /** 6 | * A {@link AsyncCloseable} is a resource that can be closed. The {@link #closeAsync()} method is invoked to request resources 7 | * release that the object is holding (such as open files). 8 | * 9 | * @since 5.1 10 | * @author Mark Paluch 11 | * @deprecated since 6.2, use {@link io.lettuce.core.api.AsyncCloseable} instead. 12 | */ 13 | @Deprecated 14 | public interface AsyncCloseable { 15 | 16 | /** 17 | * Requests to close this object and releases any system resources associated with it. If the object is already closed then 18 | * invoking this method has no effect. 19 | *

20 | * Calls to this method return a {@link CompletableFuture} that is notified with the outcome of the close request. 21 | */ 22 | CompletableFuture closeAsync(); 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/test/java/io/lettuce/core/cluster/commands/HashClusterCommandIntegrationTests.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.cluster.commands; 2 | 3 | import javax.inject.Inject; 4 | 5 | import io.lettuce.core.cluster.ClusterTestUtil; 6 | import io.lettuce.core.cluster.api.StatefulRedisClusterConnection; 7 | import io.lettuce.core.commands.HashCommandIntegrationTests; 8 | import org.junit.jupiter.api.Tag; 9 | 10 | import static io.lettuce.TestTags.INTEGRATION_TEST; 11 | 12 | /** 13 | * Integration tests for {@link io.lettuce.core.api.sync.RedisHashCommands} using Redis Cluster. 14 | * 15 | * @author Mark Paluch 16 | */ 17 | @Tag(INTEGRATION_TEST) 18 | public class HashClusterCommandIntegrationTests extends HashCommandIntegrationTests { 19 | 20 | @Inject 21 | public HashClusterCommandIntegrationTests(StatefulRedisClusterConnection connection) { 22 | super(ClusterTestUtil.redisCommandsOverCluster(connection)); 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/cluster/event/JfrAskRedirectionEvent.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.cluster.event; 2 | 3 | import jdk.jfr.Category; 4 | import jdk.jfr.Event; 5 | import jdk.jfr.Label; 6 | import jdk.jfr.StackTrace; 7 | 8 | /** 9 | * Flight recorder event variant of {@link AskRedirectionEvent}. 10 | * 11 | * @author Mark Paluch 12 | * @since 6.1 13 | */ 14 | @Category({ "Lettuce", "Cluster Events" }) 15 | @Label("ASK Redirection") 16 | @StackTrace(false) 17 | class JfrAskRedirectionEvent extends Event { 18 | 19 | private final String command; 20 | 21 | private final String key; 22 | 23 | private final int slot; 24 | 25 | private final String message; 26 | 27 | public JfrAskRedirectionEvent(RedirectionEventSupport event) { 28 | this.command = event.getCommand(); 29 | this.key = event.getKey(); 30 | this.slot = event.getSlot(); 31 | this.message = event.getMessage(); 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /src/test/java/io/lettuce/core/commands/transactional/StreamTxCommandIntegrationTests.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.commands.transactional; 2 | 3 | import javax.inject.Inject; 4 | 5 | import org.junit.jupiter.api.Disabled; 6 | import org.junit.jupiter.api.Tag; 7 | import org.junit.jupiter.api.Test; 8 | 9 | import io.lettuce.core.api.StatefulRedisConnection; 10 | import io.lettuce.core.commands.StreamCommandIntegrationTests; 11 | 12 | import static io.lettuce.TestTags.INTEGRATION_TEST; 13 | 14 | /** 15 | * @author Mark Paluch 16 | */ 17 | @Tag(INTEGRATION_TEST) 18 | class StreamTxCommandIntegrationTests extends StreamCommandIntegrationTests { 19 | 20 | @Inject 21 | StreamTxCommandIntegrationTests(StatefulRedisConnection connection) { 22 | super(TxSyncInvocationHandler.sync(connection)); 23 | } 24 | 25 | @Test 26 | @Disabled("TX over TX doesn't work") 27 | public void xreadTransactional() { 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/cluster/event/JfrMovedRedirectionEvent.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.cluster.event; 2 | 3 | import jdk.jfr.Category; 4 | import jdk.jfr.Event; 5 | import jdk.jfr.Label; 6 | import jdk.jfr.StackTrace; 7 | 8 | /** 9 | * Flight recorder event variant of {@link MovedRedirectionEvent}. 10 | * 11 | * @author Mark Paluch 12 | * @since 6.1 13 | */ 14 | @Category({ "Lettuce", "Cluster Events" }) 15 | @Label("MOVED Redirection") 16 | @StackTrace(false) 17 | class JfrMovedRedirectionEvent extends Event { 18 | 19 | private final String command; 20 | 21 | private final String key; 22 | 23 | private final int slot; 24 | 25 | private final String message; 26 | 27 | public JfrMovedRedirectionEvent(RedirectionEventSupport event) { 28 | this.command = event.getCommand(); 29 | this.key = event.getKey(); 30 | this.slot = event.getSlot(); 31 | this.message = event.getMessage(); 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/masterreplica/SentinelTopologyRefreshEvent.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.masterreplica; 2 | 3 | import io.lettuce.core.event.Event; 4 | 5 | /** 6 | * Event triggered when Redis Sentinel indicates a topology change trigger. 7 | * 8 | * @author Mark Paluch 9 | * @since 6.1 10 | */ 11 | class SentinelTopologyRefreshEvent implements Event { 12 | 13 | private final String source; 14 | 15 | private final String message; 16 | 17 | private final long delayMs; 18 | 19 | public SentinelTopologyRefreshEvent(String source, String message, long delayMs) { 20 | this.source = source; 21 | this.message = message; 22 | this.delayMs = delayMs; 23 | } 24 | 25 | public String getSource() { 26 | return source; 27 | } 28 | 29 | public String getMessage() { 30 | return message; 31 | } 32 | 33 | public long getDelayMs() { 34 | return delayMs; 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/RedisBusyException.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core; 2 | 3 | /** 4 | * Exception that gets thrown when Redis is busy executing a Lua script with a {@code BUSY} error response. 5 | * 6 | * @author Mark Paluch 7 | * @since 4.5 8 | */ 9 | @SuppressWarnings("serial") 10 | public class RedisBusyException extends RedisCommandExecutionException { 11 | 12 | /** 13 | * Create a {@code RedisBusyException} with the specified detail message. 14 | * 15 | * @param msg the detail message. 16 | */ 17 | public RedisBusyException(String msg) { 18 | super(msg); 19 | } 20 | 21 | /** 22 | * Create a {@code RedisNoScriptException} with the specified detail message and nested exception. 23 | * 24 | * @param msg the detail message. 25 | * @param cause the nested exception. 26 | */ 27 | public RedisBusyException(String msg, Throwable cause) { 28 | super(msg, cause); 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /.github/workflows/snapshot.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | name: Publish Snapshot 4 | 5 | on: 6 | push: 7 | branches: 8 | - main 9 | - '[0-9].x' 10 | workflow_dispatch: 11 | 12 | jobs: 13 | 14 | snapshot: 15 | name: Deploy Snapshot 16 | runs-on: ubuntu-latest 17 | steps: 18 | - uses: actions/checkout@v4 19 | - name: Set up publishing to maven central 20 | uses: actions/setup-java@v4 21 | with: 22 | java-version: '8' 23 | distribution: 'temurin' 24 | cache: 'maven' 25 | server-id: central 26 | server-username: MAVEN_USERNAME 27 | server-password: MAVEN_PASSWORD 28 | - name: mvn offline 29 | run: | 30 | mvn -q dependency:go-offline 31 | - name: deploy 32 | run: | 33 | mvn --no-transfer-progress deploy 34 | env: 35 | MAVEN_USERNAME: ${{secrets.OSSH_USERNAME}} 36 | MAVEN_PASSWORD: ${{secrets.OSSH_TOKEN}} 37 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/masterreplica/MasterReplicaTopologyChangedEvent.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.masterreplica; 2 | 3 | import java.util.List; 4 | 5 | import io.lettuce.core.RedisURI; 6 | import io.lettuce.core.event.Event; 7 | import io.lettuce.core.models.role.RedisNodeDescription; 8 | 9 | /** 10 | * Event triggered after obtaining the Master/Replica topology. 11 | * 12 | * @author Mark Paluch 13 | * @since 6.1 14 | */ 15 | class MasterReplicaTopologyChangedEvent implements Event { 16 | 17 | private final RedisURI source; 18 | 19 | private final List nodes; 20 | 21 | public MasterReplicaTopologyChangedEvent(RedisURI source, List nodes) { 22 | this.source = source; 23 | this.nodes = nodes; 24 | } 25 | 26 | public RedisURI getSource() { 27 | return source; 28 | } 29 | 30 | public List getNodes() { 31 | return nodes; 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /src/test/jmh/io/lettuce/core/cluster/EmptyRedisClusterClient.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.cluster; 2 | 3 | import java.net.SocketAddress; 4 | import java.util.Collections; 5 | import java.util.function.Supplier; 6 | 7 | import io.lettuce.core.EmptyStatefulRedisConnection; 8 | import io.lettuce.core.RedisChannelWriter; 9 | import io.lettuce.core.RedisURI; 10 | import io.lettuce.core.api.StatefulRedisConnection; 11 | import io.lettuce.core.codec.RedisCodec; 12 | 13 | /** 14 | * @author Mark Paluch 15 | */ 16 | class EmptyRedisClusterClient extends RedisClusterClient { 17 | 18 | public EmptyRedisClusterClient(RedisURI initialUri) { 19 | super(null, Collections.singleton(initialUri)); 20 | } 21 | 22 | StatefulRedisConnection connectToNode(RedisCodec codec, String nodeId, RedisChannelWriter clusterWriter, 23 | final Supplier socketAddressSupplier) { 24 | return EmptyStatefulRedisConnection.INSTANCE; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/cluster/event/RedirectionEventSupport.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.cluster.event; 2 | 3 | import io.lettuce.core.event.Event; 4 | 5 | /** 6 | * @author Mark Paluch 7 | */ 8 | public class RedirectionEventSupport implements Event { 9 | 10 | private final String command; 11 | 12 | private final String key; 13 | 14 | private final int slot; 15 | 16 | private final String message; 17 | 18 | public RedirectionEventSupport(String command, String key, int slot, String message) { 19 | this.command = command; 20 | this.key = key; 21 | this.slot = slot; 22 | this.message = message; 23 | } 24 | 25 | public String getCommand() { 26 | return command; 27 | } 28 | 29 | public String getKey() { 30 | return key; 31 | } 32 | 33 | public int getSlot() { 34 | return slot; 35 | } 36 | 37 | public String getMessage() { 38 | return message; 39 | } 40 | 41 | } 42 | -------------------------------------------------------------------------------- /src/test/java/io/lettuce/core/output/SocketAddressOutputUnitTests.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.output; 2 | 3 | import static io.lettuce.TestTags.UNIT_TEST; 4 | import static org.assertj.core.api.Assertions.assertThat; 5 | 6 | import java.net.InetSocketAddress; 7 | import java.nio.ByteBuffer; 8 | 9 | import org.junit.jupiter.api.Tag; 10 | import org.junit.jupiter.api.Test; 11 | 12 | import io.lettuce.core.codec.StringCodec; 13 | 14 | /** 15 | * @author Mark Paluch 16 | */ 17 | @Tag(UNIT_TEST) 18 | class SocketAddressOutputUnitTests { 19 | 20 | @Test 21 | void shouldReportSocketAddress() { 22 | 23 | SocketAddressOutput output = new SocketAddressOutput<>(StringCodec.ASCII); 24 | 25 | output.set(ByteBuffer.wrap("localhost".getBytes())); 26 | output.set(ByteBuffer.wrap("6379".getBytes())); 27 | 28 | output.complete(0); 29 | 30 | assertThat(output.get()).isNotNull().isInstanceOf(InetSocketAddress.class); 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/test/java/io/lettuce/examples/ConnectToElastiCacheMaster.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.examples; 2 | 3 | import io.lettuce.core.RedisClient; 4 | import io.lettuce.core.api.StatefulRedisConnection; 5 | import io.lettuce.core.resource.DefaultClientResources; 6 | import io.lettuce.core.resource.DirContextDnsResolver; 7 | 8 | /** 9 | * @author Mark Paluch 10 | */ 11 | public class ConnectToElastiCacheMaster { 12 | 13 | public static void main(String[] args) { 14 | 15 | // Syntax: redis://[password@]host[:port][/databaseNumber] 16 | 17 | DefaultClientResources clientResources = DefaultClientResources.builder().build(); 18 | 19 | RedisClient redisClient = RedisClient.create(clientResources, "redis://password@localhost:6379/0"); 20 | StatefulRedisConnection connection = redisClient.connect(); 21 | 22 | System.out.println("Connected to Redis"); 23 | 24 | connection.close(); 25 | redisClient.shutdown(); 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/test/java/io/lettuce/examples/ConnectToRedisClusterSSL.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.examples; 2 | 3 | import io.lettuce.core.RedisURI; 4 | import io.lettuce.core.cluster.RedisClusterClient; 5 | import io.lettuce.core.cluster.api.StatefulRedisClusterConnection; 6 | 7 | /** 8 | * @author Mark Paluch 9 | */ 10 | public class ConnectToRedisClusterSSL { 11 | 12 | public static void main(String[] args) { 13 | 14 | // Syntax: rediss://[password@]host[:port] 15 | RedisURI redisURI = RedisURI.create("rediss://password@localhost:7379"); 16 | redisURI.setVerifyPeer(false); // depending on your setup, you might want to disable peer verification 17 | 18 | RedisClusterClient redisClient = RedisClusterClient.create(redisURI); 19 | StatefulRedisClusterConnection connection = redisClient.connect(); 20 | 21 | System.out.println("Connected to Redis"); 22 | 23 | connection.close(); 24 | redisClient.shutdown(); 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/RedisLoadingException.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core; 2 | 3 | /** 4 | * Exception that gets thrown when Redis is loading a dataset into memory and replying with a {@code LOADING} error response. 5 | * 6 | * @author Mark Paluch 7 | * @since 4.5 8 | */ 9 | @SuppressWarnings("serial") 10 | public class RedisLoadingException extends RedisCommandExecutionException { 11 | 12 | /** 13 | * Create a {@code RedisLoadingException} with the specified detail message. 14 | * 15 | * @param msg the detail message. 16 | */ 17 | public RedisLoadingException(String msg) { 18 | super(msg); 19 | } 20 | 21 | /** 22 | * Create a {@code RedisLoadingException} with the specified detail message and nested exception. 23 | * 24 | * @param msg the detail message. 25 | * @param cause the nested exception. 26 | */ 27 | public RedisLoadingException(String msg, Throwable cause) { 28 | super(msg, cause); 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/protocol/PushHandler.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.protocol; 2 | 3 | import java.util.Collection; 4 | 5 | import io.lettuce.core.api.push.PushListener; 6 | 7 | /** 8 | * A handler object that provides access to {@link PushListener}. 9 | * 10 | * @author Mark Paluch 11 | * @since 6.0 12 | */ 13 | public interface PushHandler { 14 | 15 | /** 16 | * Add a new {@link PushListener listener}. 17 | * 18 | * @param listener the listener, must not be {@code null}. 19 | */ 20 | void addListener(PushListener listener); 21 | 22 | /** 23 | * Remove an existing {@link PushListener listener}. 24 | * 25 | * @param listener the listener, must not be {@code null}. 26 | */ 27 | void removeListener(PushListener listener); 28 | 29 | /** 30 | * Returns a collection of {@link PushListener}. 31 | * 32 | * @return the collection of listeners. 33 | */ 34 | Collection getPushListeners(); 35 | 36 | } 37 | -------------------------------------------------------------------------------- /src/test/java/io/lettuce/test/resource/DefaultRedisClient.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.test.resource; 2 | 3 | import io.lettuce.core.RedisClient; 4 | import io.lettuce.core.RedisURI; 5 | import io.lettuce.test.settings.TestSettings; 6 | 7 | /** 8 | * @author Mark Paluch 9 | * @author Hari Mani 10 | */ 11 | public class DefaultRedisClient { 12 | 13 | private static final DefaultRedisClient instance = new DefaultRedisClient(); 14 | 15 | private final RedisClient redisClient; 16 | 17 | private DefaultRedisClient() { 18 | redisClient = RedisClient.create(RedisURI.Builder.redis(TestSettings.host(), TestSettings.port()).build()); 19 | Runtime.getRuntime().addShutdownHook(new Thread(() -> FastShutdown.shutdown(redisClient))); 20 | } 21 | 22 | /** 23 | * Do not close the client. 24 | * 25 | * @return the default redis client for the tests. 26 | */ 27 | public static RedisClient get() { 28 | return instance.redisClient; 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/OrderingReadFromAccessor.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core; 2 | 3 | /** 4 | * Accessor for {@link ReadFrom} ordering. Internal utility class. 5 | * 6 | * @author Mark Paluch 7 | * @since 5.2 8 | */ 9 | public abstract class OrderingReadFromAccessor { 10 | 11 | /** 12 | * Utility constructor. 13 | */ 14 | private OrderingReadFromAccessor() { 15 | } 16 | 17 | /** 18 | * Returns whether this {@link ReadFrom} requires ordering of the resulting 19 | * {@link io.lettuce.core.models.role.RedisNodeDescription nodes}. 20 | * 21 | * @return {@code true} if code using {@link ReadFrom} should retain ordering or {@code false} to allow reordering of 22 | * {@link io.lettuce.core.models.role.RedisNodeDescription nodes}. 23 | * @since 5.2 24 | * @see ReadFrom#isOrderSensitive() 25 | */ 26 | public static boolean isOrderSensitive(ReadFrom readFrom) { 27 | return readFrom.isOrderSensitive(); 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/cluster/event/JfrTopologyRefreshEvent.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.cluster.event; 2 | 3 | import java.util.StringJoiner; 4 | 5 | import jdk.jfr.Category; 6 | import jdk.jfr.Event; 7 | import jdk.jfr.Label; 8 | import jdk.jfr.StackTrace; 9 | import io.lettuce.core.RedisURI; 10 | 11 | /** 12 | * Flight recorder event variant of {@link TopologyRefreshEvent}. 13 | * 14 | * @author Mark Paluch 15 | * @since 6.1 16 | */ 17 | @Category({ "Lettuce", "Cluster Events" }) 18 | @Label("Topology Refresh") 19 | @StackTrace(value = false) 20 | class JfrTopologyRefreshEvent extends Event { 21 | 22 | private final String sources; 23 | 24 | public JfrTopologyRefreshEvent(TopologyRefreshEvent event) { 25 | 26 | StringJoiner joiner = new StringJoiner(", "); 27 | 28 | for (RedisURI redisURI : event.getTopologyRefreshSource()) { 29 | joiner.add(redisURI.toString()); 30 | } 31 | 32 | this.sources = joiner.toString(); 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/masterreplica/RedisClientNodeConnectionFactory.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.masterreplica; 2 | 3 | import java.util.concurrent.CompletableFuture; 4 | 5 | import io.lettuce.core.RedisClient; 6 | import io.lettuce.core.RedisURI; 7 | import io.lettuce.core.api.StatefulRedisConnection; 8 | import io.lettuce.core.codec.RedisCodec; 9 | 10 | /** 11 | * {@link NodeConnectionFactory} implementation that on {@link RedisClient}. 12 | * 13 | * @author Mark Paluch 14 | */ 15 | class RedisClientNodeConnectionFactory implements NodeConnectionFactory { 16 | 17 | private final RedisClient client; 18 | 19 | RedisClientNodeConnectionFactory(RedisClient client) { 20 | this.client = client; 21 | } 22 | 23 | @Override 24 | public CompletableFuture> connectToNodeAsync(RedisCodec codec, 25 | RedisURI redisURI) { 26 | return client.connectAsync(codec, redisURI).toCompletableFuture(); 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/cluster/PartitionSelectorException.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.cluster; 2 | 3 | import io.lettuce.core.cluster.models.partitions.Partitions; 4 | 5 | /** 6 | * Exception thrown when a partition selection fails (slot not covered, no read candidates available). 7 | * 8 | * @author Mark Paluch 9 | * @since 5.1 10 | */ 11 | @SuppressWarnings("serial") 12 | public class PartitionSelectorException extends PartitionException { 13 | 14 | private final Partitions partitions; 15 | 16 | /** 17 | * Create a {@code UnknownPartitionException} with the specified detail message. 18 | * 19 | * @param msg the detail message. 20 | * @param partitions read-only view of the current topology view. 21 | */ 22 | public PartitionSelectorException(String msg, Partitions partitions) { 23 | 24 | super(msg); 25 | this.partitions = partitions; 26 | } 27 | 28 | public Partitions getPartitions() { 29 | return partitions; 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/test/resources/spring-test.xml: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/cluster/topology/RedisClusterNodeSnapshot.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.cluster.topology; 2 | 3 | import io.lettuce.core.cluster.models.partitions.RedisClusterNode; 4 | 5 | /** 6 | * @author Mark Paluch 7 | */ 8 | @SuppressWarnings("serial") 9 | class RedisClusterNodeSnapshot extends RedisClusterNode { 10 | 11 | private Long latencyNs; 12 | 13 | private Integer connectedClients; 14 | 15 | public RedisClusterNodeSnapshot() { 16 | } 17 | 18 | public RedisClusterNodeSnapshot(RedisClusterNode redisClusterNode) { 19 | super(redisClusterNode); 20 | } 21 | 22 | Long getLatencyNs() { 23 | return latencyNs; 24 | } 25 | 26 | void setLatencyNs(Long latencyNs) { 27 | this.latencyNs = latencyNs; 28 | } 29 | 30 | Integer getConnectedClients() { 31 | return connectedClients; 32 | } 33 | 34 | void setConnectedClients(Integer connectedClients) { 35 | this.connectedClients = connectedClients; 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/tracing/SocketAddressEndpoint.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.tracing; 2 | 3 | import java.net.InetSocketAddress; 4 | import java.net.SocketAddress; 5 | 6 | /** 7 | * {@link Tracing.Endpoint} based on a {@link SocketAddress}. 8 | * 9 | * @author Mark Paluch 10 | * @since 6.3 11 | */ 12 | class SocketAddressEndpoint implements Tracing.Endpoint { 13 | 14 | private final SocketAddress socketAddress; 15 | 16 | public SocketAddressEndpoint(SocketAddress socketAddress) { 17 | this.socketAddress = socketAddress; 18 | } 19 | 20 | public SocketAddress getSocketAddress() { 21 | return socketAddress; 22 | } 23 | 24 | @Override 25 | public String toString() { 26 | 27 | if (socketAddress instanceof InetSocketAddress) { 28 | InetSocketAddress inet = (InetSocketAddress) socketAddress; 29 | return inet.getHostString() + ":" + inet.getPort(); 30 | } 31 | 32 | return socketAddress.toString(); 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/cluster/api/sync/NodeSelectionCommands.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.cluster.api.sync; 2 | 3 | import io.lettuce.core.cluster.api.NodeSelectionSupport; 4 | 5 | /** 6 | * Synchronous and thread-safe Redis API to execute commands on a {@link NodeSelectionSupport}. 7 | * 8 | * @author Mark Paluch 9 | * @author Tihomir Mateev 10 | */ 11 | public interface NodeSelectionCommands extends BaseNodeSelectionCommands, NodeSelectionFunctionCommands, 12 | NodeSelectionGeoCommands, NodeSelectionHashCommands, NodeSelectionHLLCommands, 13 | NodeSelectionKeyCommands, NodeSelectionListCommands, NodeSelectionScriptingCommands, 14 | NodeSelectionServerCommands, NodeSelectionSetCommands, NodeSelectionSortedSetCommands, 15 | NodeSelectionStreamCommands, NodeSelectionStringCommands, NodeSelectionJsonCommands, 16 | NodeSelectionVectorSetCommands, NodeSelectionSearchCommands { 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/models/role/RedisMasterInstance.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.models.role; 2 | 3 | import java.util.List; 4 | 5 | /** 6 | * Represents a upstream (master) instance. 7 | * 8 | * @author Mark Paluch 9 | * @since 3.0 10 | */ 11 | @SuppressWarnings("serial") 12 | public class RedisMasterInstance extends RedisUpstreamInstance { 13 | 14 | public RedisMasterInstance() { 15 | } 16 | 17 | /** 18 | * Constructs a {@link RedisMasterInstance} 19 | * 20 | * @param replicationOffset the replication offset 21 | * @param replicas list of replicas, must not be {@code null} but may be empty 22 | */ 23 | public RedisMasterInstance(long replicationOffset, List replicas) { 24 | super(replicationOffset, replicas); 25 | } 26 | 27 | /** 28 | * @return always {@link io.lettuce.core.models.role.RedisInstance.Role#MASTER} 29 | */ 30 | @Override 31 | public Role getRole() { 32 | return Role.MASTER; 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/RedisNoScriptException.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core; 2 | 3 | /** 4 | * Exception that gets thrown when Redis indicates absence of a Lua script referenced by its SHA1 digest with a {@code NOSCRIPT} 5 | * error response. 6 | * 7 | * @author Mark Paluch 8 | * @since 4.5 9 | */ 10 | @SuppressWarnings("serial") 11 | public class RedisNoScriptException extends RedisCommandExecutionException { 12 | 13 | /** 14 | * Create a {@code RedisNoScriptException} with the specified detail message. 15 | * 16 | * @param msg the detail message. 17 | */ 18 | public RedisNoScriptException(String msg) { 19 | super(msg); 20 | } 21 | 22 | /** 23 | * Create a {@code RedisNoScriptException} with the specified detail message and nested exception. 24 | * 25 | * @param msg the detail message. 26 | * @param cause the nested exception. 27 | */ 28 | public RedisNoScriptException(String msg, Throwable cause) { 29 | super(msg, cause); 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/dynamic/CommandMethodVerifier.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.dynamic; 2 | 3 | import io.lettuce.core.dynamic.segment.CommandSegments; 4 | 5 | /** 6 | * Verifies {@link CommandMethod} declarations by checking available Redis commands. 7 | * 8 | * @author Mark Paluch 9 | * @since 5.0 10 | */ 11 | @FunctionalInterface 12 | interface CommandMethodVerifier { 13 | 14 | /** 15 | * Default instance that does not verify commands. 16 | */ 17 | CommandMethodVerifier NONE = (commandSegments, commandMethod) -> { 18 | }; 19 | 20 | /** 21 | * Verify a {@link CommandMethod} with its {@link CommandSegments}. This method verifies that the command exists and that 22 | * the required number of arguments is declared. 23 | * 24 | * @param commandSegments must not be {@code null}. 25 | * @param commandMethod must not be {@code null}. 26 | */ 27 | void validate(CommandSegments commandSegments, CommandMethod commandMethod) throws CommandMethodSyntaxException; 28 | 29 | } 30 | -------------------------------------------------------------------------------- /src/test/java/io/lettuce/core/protocol/TransactionalCommandUnitTests.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.protocol; 2 | 3 | import static io.lettuce.TestTags.UNIT_TEST; 4 | import static org.assertj.core.api.Assertions.assertThat; 5 | 6 | import org.junit.jupiter.api.Tag; 7 | import org.junit.jupiter.api.Test; 8 | 9 | import io.lettuce.core.RedisException; 10 | import io.lettuce.core.codec.StringCodec; 11 | import io.lettuce.core.output.StatusOutput; 12 | 13 | /** 14 | * @author Mark Paluch 15 | */ 16 | @Tag(UNIT_TEST) 17 | class TransactionalCommandUnitTests { 18 | 19 | @Test 20 | void shouldCompleteOnException() { 21 | 22 | RedisCommand inner = new Command<>(CommandType.SET, new StatusOutput<>(StringCodec.UTF8)); 23 | 24 | TransactionalCommand command = new TransactionalCommand<>(new AsyncCommand<>(inner)); 25 | 26 | command.completeExceptionally(new RedisException("foo")); 27 | 28 | assertThat(command).isCompletedExceptionally(); 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/dynamic/BatchTasks.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.dynamic; 2 | 3 | import java.util.Collections; 4 | import java.util.Iterator; 5 | import java.util.List; 6 | 7 | import io.lettuce.core.protocol.RedisCommand; 8 | 9 | /** 10 | * Result of a batching request. Contains references to the batched {@link RedisCommand}s. 11 | * 12 | * @author Mark Paluch 13 | * @since 5.0 14 | */ 15 | class BatchTasks implements Iterable> { 16 | 17 | public static final BatchTasks EMPTY = new BatchTasks(Collections.emptyList()); 18 | 19 | private final List> futures; 20 | 21 | BatchTasks(List> futures) { 22 | this.futures = futures; 23 | } 24 | 25 | @Override 26 | public Iterator> iterator() { 27 | return futures.iterator(); 28 | } 29 | 30 | @SuppressWarnings("rawtypes") 31 | public RedisCommand[] toArray() { 32 | return futures.toArray(new RedisCommand[0]); 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/test/java/io/lettuce/examples/ReadWriteExample.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.examples; 2 | 3 | import io.lettuce.core.RedisClient; 4 | import io.lettuce.core.RedisURI; 5 | import io.lettuce.core.api.StatefulRedisConnection; 6 | import io.lettuce.core.api.sync.RedisCommands; 7 | 8 | /** 9 | * @author Mark Paluch 10 | */ 11 | public class ReadWriteExample { 12 | 13 | public static void main(String[] args) { 14 | 15 | // Syntax: redis://[password@]host[:port][/databaseNumber] 16 | RedisClient redisClient = RedisClient.create(RedisURI.create("redis://password@localhost:6379/0")); 17 | 18 | StatefulRedisConnection connection = redisClient.connect(); 19 | 20 | System.out.println("Connected to Redis"); 21 | 22 | RedisCommands sync = connection.sync(); 23 | 24 | sync.set("foo", "bar"); 25 | String value = sync.get("foo"); 26 | System.out.println(value); 27 | 28 | connection.close(); 29 | redisClient.shutdown(); 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/masterreplica/NodeConnectionFactory.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.masterreplica; 2 | 3 | import java.net.SocketAddress; 4 | import java.util.concurrent.CompletableFuture; 5 | 6 | import io.lettuce.core.RedisURI; 7 | import io.lettuce.core.api.StatefulRedisConnection; 8 | import io.lettuce.core.codec.RedisCodec; 9 | 10 | /** 11 | * Factory interface to obtain {@link StatefulRedisConnection connections} to Redis nodes. 12 | * 13 | * @author Mark Paluch 14 | * @since 4.4 15 | */ 16 | interface NodeConnectionFactory { 17 | 18 | /** 19 | * Connects to a {@link SocketAddress} with the given {@link RedisCodec} asynchronously. 20 | * 21 | * @param codec must not be {@code null}. 22 | * @param redisURI must not be {@code null}. 23 | * @param Key type. 24 | * @param Value type. 25 | * @return a new {@link StatefulRedisConnection} 26 | */ 27 | CompletableFuture> connectToNodeAsync(RedisCodec codec, RedisURI redisURI); 28 | 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/dynamic/intercept/MethodInterceptor.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.dynamic.intercept; 2 | 3 | /** 4 | * Intercepts calls on an interface on its way to the target. These are nested "on top" of the target. 5 | * 6 | *

7 | * Implementing classes are required to implement the {@link #invoke(MethodInvocation)} method to modify the original behavior. 8 | * 9 | * @author Mark Paluch 10 | * @since 5.0 11 | */ 12 | public interface MethodInterceptor { 13 | 14 | /** 15 | * Implement this method to perform extra treatments before and after the invocation. Polite implementations would certainly 16 | * like to invoke {@link MethodInvocation#proceed()}. 17 | * 18 | * @param invocation the method invocation 19 | * @return the result of the call to {@link MethodInvocation#proceed()}, might be intercepted by the interceptor. 20 | * @throws Throwable if the interceptors or the target-object throws an exception. 21 | */ 22 | Object invoke(MethodInvocation invocation) throws Throwable; 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/masterreplica/JfrSentinelTopologyRefreshEvent.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.masterreplica; 2 | 3 | import static jdk.jfr.Timespan.*; 4 | 5 | import jdk.jfr.Category; 6 | import jdk.jfr.Event; 7 | import jdk.jfr.Label; 8 | import jdk.jfr.StackTrace; 9 | import jdk.jfr.Timespan; 10 | 11 | /** 12 | * Flight recorder event variant of {@link SentinelTopologyRefreshEvent}. 13 | * 14 | * @author Mark Paluch 15 | * @since 6.1 16 | */ 17 | @Category({ "Lettuce", "Master/Replica Events" }) 18 | @Label("Sentinel Topology Refresh Trigger") 19 | @StackTrace(false) 20 | class JfrSentinelTopologyRefreshEvent extends Event { 21 | 22 | private final String source; 23 | 24 | private final String message; 25 | 26 | @Timespan(value = MILLISECONDS) 27 | private final long delay; 28 | 29 | public JfrSentinelTopologyRefreshEvent(SentinelTopologyRefreshEvent event) { 30 | this.source = event.getSource(); 31 | this.message = event.getMessage(); 32 | this.delay = event.getDelayMs(); 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/test/java/io/lettuce/test/MutableClock.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.test; 2 | 3 | import java.time.Clock; 4 | import java.time.Duration; 5 | import java.time.Instant; 6 | import java.time.ZoneId; 7 | import java.util.concurrent.atomic.AtomicReference; 8 | 9 | public class MutableClock extends Clock { 10 | 11 | AtomicReference currentTime = new AtomicReference<>(Instant.now()); 12 | 13 | public MutableClock() { 14 | this.currentTime.set(Instant.now()); 15 | } 16 | 17 | public MutableClock(Instant startTime) { 18 | this.currentTime.set(startTime); 19 | } 20 | 21 | @Override 22 | public ZoneId getZone() { 23 | return ZoneId.systemDefault(); 24 | } 25 | 26 | @Override 27 | public Clock withZone(ZoneId zone) { 28 | return this; 29 | } 30 | 31 | @Override 32 | public Instant instant() { 33 | return currentTime.get(); 34 | } 35 | 36 | public void tick(Duration duration) { 37 | currentTime.set(currentTime.get().plus(duration)); 38 | } 39 | 40 | }; 41 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/output/ValueScanStreamingOutput.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.output; 2 | 3 | import java.nio.ByteBuffer; 4 | 5 | import io.lettuce.core.StreamScanCursor; 6 | import io.lettuce.core.codec.RedisCodec; 7 | 8 | /** 9 | * Streaming API for multiple Values. You can implement this interface in order to receive a call to {@code onValue} on every 10 | * key. 11 | * 12 | * @param Key type. 13 | * @param Value type. 14 | * @author Mark Paluch 15 | */ 16 | public class ValueScanStreamingOutput extends ScanOutput { 17 | 18 | private final ValueStreamingChannel channel; 19 | 20 | public ValueScanStreamingOutput(RedisCodec codec, ValueStreamingChannel channel) { 21 | super(codec, new StreamScanCursor()); 22 | this.channel = channel; 23 | } 24 | 25 | @Override 26 | protected void setOutput(ByteBuffer bytes) { 27 | channel.onValue(bytes == null ? null : codec.decodeValue(bytes)); 28 | output.setCount(output.getCount() + 1); 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/RedisCommandTimeoutException.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core; 2 | 3 | /** 4 | * Exception thrown when the command waiting timeout is exceeded. 5 | * 6 | * @author Mark Paluch 7 | */ 8 | @SuppressWarnings("serial") 9 | public class RedisCommandTimeoutException extends RedisException { 10 | 11 | /** 12 | * Create a {@code RedisCommandTimeoutException} with a default message. 13 | */ 14 | public RedisCommandTimeoutException() { 15 | super("Command timed out"); 16 | } 17 | 18 | /** 19 | * Create a {@code RedisCommandTimeoutException} with the specified detail message. 20 | * 21 | * @param msg the detail message. 22 | */ 23 | public RedisCommandTimeoutException(String msg) { 24 | super(msg); 25 | } 26 | 27 | /** 28 | * Create a {@code RedisException} with the specified nested exception. 29 | * 30 | * @param cause the nested exception. 31 | */ 32 | public RedisCommandTimeoutException(Throwable cause) { 33 | super(cause); 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/output/EncodedComplexOutput.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2025, Redis Ltd. and Contributors 3 | * All rights reserved. 4 | * 5 | * Licensed under the MIT License. 6 | */ 7 | 8 | package io.lettuce.core.output; 9 | 10 | import io.lettuce.core.codec.RedisCodec; 11 | 12 | import java.nio.ByteBuffer; 13 | 14 | public class EncodedComplexOutput extends ComplexOutput { 15 | 16 | /** 17 | * Constructs a new instance of the {@link ComplexOutput} 18 | * 19 | * @param codec the {@link RedisCodec} to be applied 20 | * @param parser 21 | */ 22 | public EncodedComplexOutput(RedisCodec codec, ComplexDataParser parser) { 23 | super(codec, parser); 24 | } 25 | 26 | @Override 27 | public void set(ByteBuffer bytes) { 28 | data.storeObject(bytes == null ? null : bytes.asReadOnlyBuffer()); 29 | } 30 | 31 | @Override 32 | public void setSingle(ByteBuffer bytes) { 33 | data.storeObject(bytes == null ? null : bytes.asReadOnlyBuffer()); 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/event/connection/JfrConnectedEvent.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.event.connection; 2 | 3 | import jdk.jfr.Category; 4 | import jdk.jfr.Event; 5 | import jdk.jfr.Label; 6 | import jdk.jfr.StackTrace; 7 | 8 | /** 9 | * Flight recorder event variant of {@link ConnectedEvent}. 10 | * 11 | * @author Mark Paluch 12 | * @since 6.1 13 | */ 14 | @Category({ "Lettuce", "Connection Events" }) 15 | @Label("Connected") 16 | @StackTrace(false) 17 | class JfrConnectedEvent extends Event { 18 | 19 | private final String redisUri; 20 | 21 | private final String epId; 22 | 23 | private final String channelId; 24 | 25 | private final String local; 26 | 27 | private final String remote; 28 | 29 | public JfrConnectedEvent(ConnectionEventSupport event) { 30 | this.redisUri = event.getRedisUri(); 31 | this.epId = event.getChannelId(); 32 | this.channelId = event.getChannelId(); 33 | this.local = event.localAddress().toString(); 34 | this.remote = event.remoteAddress().toString(); 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/output/KeyScanStreamingOutput.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.output; 2 | 3 | import java.nio.ByteBuffer; 4 | 5 | import io.lettuce.core.StreamScanCursor; 6 | import io.lettuce.core.codec.RedisCodec; 7 | 8 | /** 9 | * Streaming API for multiple Keys. You can implement this interface in order to receive a call to {@code onKey} on every key. 10 | * Key uniqueness is not guaranteed. 11 | * 12 | * @param Key type. 13 | * @param Value type. 14 | * @author Mark Paluch 15 | */ 16 | public class KeyScanStreamingOutput extends ScanOutput { 17 | 18 | private final KeyStreamingChannel channel; 19 | 20 | public KeyScanStreamingOutput(RedisCodec codec, KeyStreamingChannel channel) { 21 | super(codec, new StreamScanCursor()); 22 | this.channel = channel; 23 | } 24 | 25 | @Override 26 | protected void setOutput(ByteBuffer bytes) { 27 | channel.onKey(bytes == null ? null : codec.decodeKey(bytes)); 28 | output.setCount(output.getCount() + 1); 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /src/test/java/io/lettuce/core/ByteBufferCodec.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core; 2 | 3 | import java.nio.ByteBuffer; 4 | 5 | import io.lettuce.core.codec.RedisCodec; 6 | 7 | /** 8 | * @author Mark Paluch 9 | */ 10 | public class ByteBufferCodec implements RedisCodec { 11 | 12 | @Override 13 | public ByteBuffer decodeKey(ByteBuffer bytes) { 14 | 15 | ByteBuffer decoupled = ByteBuffer.allocate(bytes.remaining()); 16 | decoupled.put(bytes); 17 | return (ByteBuffer) decoupled.flip(); 18 | } 19 | 20 | @Override 21 | public ByteBuffer decodeValue(ByteBuffer bytes) { 22 | 23 | ByteBuffer decoupled = ByteBuffer.allocate(bytes.remaining()); 24 | decoupled.put(bytes); 25 | return (ByteBuffer) decoupled.flip(); 26 | } 27 | 28 | @Override 29 | public ByteBuffer encodeKey(ByteBuffer key) { 30 | return key.asReadOnlyBuffer(); 31 | } 32 | 33 | @Override 34 | public ByteBuffer encodeValue(ByteBuffer value) { 35 | return value.asReadOnlyBuffer(); 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/test/java/io/lettuce/test/KeyValueStreamingAdapter.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.test; 2 | 3 | import java.util.LinkedHashMap; 4 | import java.util.Map; 5 | import java.util.concurrent.locks.ReentrantLock; 6 | 7 | import io.lettuce.core.output.KeyStreamingChannel; 8 | import io.lettuce.core.output.KeyValueStreamingChannel; 9 | 10 | /** 11 | * Adapter for a {@link KeyStreamingChannel}. Stores the output in a map. 12 | * 13 | * @param Key type. 14 | * @param Value type. 15 | * @author Mark Paluch 16 | * @since 3.0 17 | */ 18 | public class KeyValueStreamingAdapter implements KeyValueStreamingChannel { 19 | 20 | private final Map map = new LinkedHashMap<>(); 21 | 22 | private final ReentrantLock lock = new ReentrantLock(); 23 | 24 | @Override 25 | public void onKeyValue(K key, V value) { 26 | 27 | lock.lock(); 28 | try { 29 | map.put(key, value); 30 | } finally { 31 | lock.unlock(); 32 | } 33 | } 34 | 35 | public Map getMap() { 36 | return map; 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/event/connection/JfrDisconnectedEvent.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.event.connection; 2 | 3 | import jdk.jfr.Category; 4 | import jdk.jfr.Event; 5 | import jdk.jfr.Label; 6 | import jdk.jfr.StackTrace; 7 | 8 | /** 9 | * Flight recorder event variant of {@link DisconnectedEvent}. 10 | * 11 | * @author Mark Paluch 12 | * @since 6.1 13 | */ 14 | @Category({ "Lettuce", "Connection Events" }) 15 | @Label("Disconnected") 16 | @StackTrace(false) 17 | class JfrDisconnectedEvent extends Event { 18 | 19 | private final String redisUri; 20 | 21 | private final String epId; 22 | 23 | private final String channelId; 24 | 25 | private final String local; 26 | 27 | private final String remote; 28 | 29 | public JfrDisconnectedEvent(ConnectionEventSupport event) { 30 | this.redisUri = event.getRedisUri(); 31 | this.epId = event.getChannelId(); 32 | this.channelId = event.getChannelId(); 33 | this.local = event.localAddress().toString(); 34 | this.remote = event.remoteAddress().toString(); 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/output/SocketAddressOutput.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.output; 2 | 3 | import java.net.InetSocketAddress; 4 | import java.net.SocketAddress; 5 | import java.nio.ByteBuffer; 6 | 7 | import io.lettuce.core.codec.RedisCodec; 8 | 9 | /** 10 | * Output capturing a hostname and port (both string elements) into a {@link SocketAddress}. 11 | * 12 | * @author Mark Paluch 13 | * @since 5.0.1 14 | */ 15 | public class SocketAddressOutput extends CommandOutput { 16 | 17 | private String hostname; 18 | 19 | private boolean hasHostname; 20 | 21 | public SocketAddressOutput(RedisCodec codec) { 22 | super(codec, null); 23 | } 24 | 25 | @Override 26 | public void set(ByteBuffer bytes) { 27 | 28 | if (!hasHostname) { 29 | hostname = decodeString(bytes); 30 | hasHostname = true; 31 | return; 32 | } 33 | 34 | int port = Integer.parseInt(decodeString(bytes)); 35 | output = InetSocketAddress.createUnresolved(hostname, port); 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/json/JsonType.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2024, Redis Ltd. and Contributors 3 | * All rights reserved. 4 | * 5 | * Licensed under the MIT License. 6 | */ 7 | 8 | package io.lettuce.core.json; 9 | 10 | /** 11 | * JSON types as returned by the JSON.TYPE command 12 | * 13 | * @see io.lettuce.core.api.sync.RedisCommands#jsonType 14 | * @since 6.5 15 | * @author Tihomir Mateev 16 | */ 17 | public enum JsonType { 18 | 19 | OBJECT, ARRAY, STRING, INTEGER, NUMBER, BOOLEAN, UNKNOWN; 20 | 21 | public static JsonType fromString(String s) { 22 | switch (s) { 23 | case "object": 24 | return OBJECT; 25 | case "array": 26 | return ARRAY; 27 | case "string": 28 | return STRING; 29 | case "integer": 30 | return INTEGER; 31 | case "number": 32 | return NUMBER; 33 | case "boolean": 34 | return BOOLEAN; 35 | default: 36 | return UNKNOWN; 37 | } 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/output/MapScanOutput.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.output; 2 | 3 | import java.nio.ByteBuffer; 4 | 5 | import io.lettuce.core.MapScanCursor; 6 | import io.lettuce.core.codec.RedisCodec; 7 | 8 | /** 9 | * {@link io.lettuce.core.MapScanCursor} for scan cursor output. 10 | * 11 | * @param Key type. 12 | * @param Value type. 13 | * @author Mark Paluch 14 | */ 15 | public class MapScanOutput extends ScanOutput> { 16 | 17 | private K key; 18 | 19 | private boolean hasKey; 20 | 21 | public MapScanOutput(RedisCodec codec) { 22 | super(codec, new MapScanCursor()); 23 | } 24 | 25 | @Override 26 | protected void setOutput(ByteBuffer bytes) { 27 | 28 | if (!hasKey) { 29 | key = codec.decodeKey(bytes); 30 | hasKey = true; 31 | return; 32 | } 33 | 34 | V value = (bytes == null) ? null : codec.decodeValue(bytes); 35 | output.getMap().put(key, value); 36 | key = null; 37 | hasKey = false; 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /src/test/java/io/lettuce/core/ScanCursorUnitTests.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core; 2 | 3 | import static io.lettuce.TestTags.UNIT_TEST; 4 | import static org.assertj.core.api.Assertions.assertThat; 5 | import static org.assertj.core.api.Assertions.assertThatThrownBy; 6 | 7 | import org.junit.jupiter.api.Tag; 8 | import org.junit.jupiter.api.Test; 9 | 10 | /** 11 | * @author Mark Paluch 12 | */ 13 | @Tag(UNIT_TEST) 14 | class ScanCursorUnitTests { 15 | 16 | @Test 17 | void testFactory() { 18 | ScanCursor scanCursor = ScanCursor.of("dummy"); 19 | assertThat(scanCursor.getCursor()).isEqualTo("dummy"); 20 | assertThat(scanCursor.isFinished()).isFalse(); 21 | } 22 | 23 | @Test 24 | void setCursorOnImmutableInstance() { 25 | assertThatThrownBy(() -> ScanCursor.INITIAL.setCursor("")).isInstanceOf(UnsupportedOperationException.class); 26 | } 27 | 28 | @Test 29 | void setFinishedOnImmutableInstance() { 30 | assertThatThrownBy(() -> ScanCursor.INITIAL.setFinished(false)).isInstanceOf(UnsupportedOperationException.class); 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/test/java/io/lettuce/core/CopyArgsUnitTests.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core; 2 | 3 | import io.lettuce.core.codec.StringCodec; 4 | import io.lettuce.core.protocol.CommandArgs; 5 | import org.junit.jupiter.api.Tag; 6 | import org.junit.jupiter.api.Test; 7 | 8 | import static io.lettuce.TestTags.UNIT_TEST; 9 | import static org.assertj.core.api.Assertions.*; 10 | 11 | /** 12 | * Unit tests for {@link CopyArgs}. 13 | * 14 | * @author Mark Paluch 15 | */ 16 | @Tag(UNIT_TEST) 17 | class CopyArgsUnitTests { 18 | 19 | @Test 20 | void shouldRenderFullArgs() { 21 | 22 | CommandArgs args = new CommandArgs<>(StringCodec.UTF8); 23 | 24 | CopyArgs.Builder.destinationDb(1).replace(true).build(args); 25 | 26 | assertThat(args.toCommandString()).isEqualTo("DB 1 REPLACE"); 27 | } 28 | 29 | @Test 30 | void shouldRenderNoArgs() { 31 | 32 | CommandArgs args = new CommandArgs<>(StringCodec.UTF8); 33 | 34 | CopyArgs.Builder.replace(false).build(args); 35 | 36 | assertThat(args.toCommandString()).isEmpty(); 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/cluster/ClusterPushHandler.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.cluster; 2 | 3 | import java.util.Collection; 4 | 5 | import io.lettuce.core.cluster.api.push.RedisClusterPushListener; 6 | 7 | /** 8 | * A handler object that provides access to {@link RedisClusterPushListener}. 9 | * 10 | * @author Mark Paluch 11 | * @since 6.0 12 | */ 13 | public interface ClusterPushHandler { 14 | 15 | /** 16 | * Add a new {@link RedisClusterPushListener listener}. 17 | * 18 | * @param listener the listener, must not be {@code null}. 19 | */ 20 | void addListener(RedisClusterPushListener listener); 21 | 22 | /** 23 | * Remove an existing {@link RedisClusterPushListener listener}. 24 | * 25 | * @param listener the listener, must not be {@code null}. 26 | */ 27 | void removeListener(RedisClusterPushListener listener); 28 | 29 | /** 30 | * Returns a collection of {@link RedisClusterPushListener}. 31 | * 32 | * @return the collection of listeners. 33 | */ 34 | Collection getPushListeners(); 35 | 36 | } 37 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/Feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: 🚀 Feature Request 3 | about: I have a suggestion (and may want to implement it 🙂)! 4 | labels: 'type: waiting-for-triage' 5 | --- 6 | 7 | ## Feature Request 8 | 9 | 10 | 11 | #### Is your feature request related to a problem? Please describe 12 | 13 | A clear and concise description of what the problem is. Ex. I have an issue when [...] 14 | 15 | #### Describe the solution you'd like 16 | 17 | A clear and concise description of what you want to happen. Add any considered drawbacks. 18 | 19 | #### Describe alternatives you've considered 20 | 21 | A clear and concise description of any alternative solutions or features you've considered. 22 | 23 | #### Teachability, Documentation, Adoption, Migration Strategy 24 | 25 | If you can, explain how users will be able to use this and possibly write out a version the docs. 26 | Maybe a screenshot or design? 27 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/dynamic/CommandCreationException.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.dynamic; 2 | 3 | import io.lettuce.core.RedisException; 4 | 5 | /** 6 | * Exception thrown if a command cannot be constructed from a {@link CommandMethod}. 7 | * 8 | * @author Mark Paluch 9 | * @since 5.0 10 | */ 11 | @SuppressWarnings("serial") 12 | public class CommandCreationException extends RedisException { 13 | 14 | private final CommandMethod commandMethod; 15 | 16 | /** 17 | * Create a new {@link CommandCreationException} given {@link CommandMethod} and a message. 18 | * 19 | * @param commandMethod must not be {@code null}. 20 | * @param msg must not be {@code null}. 21 | */ 22 | public CommandCreationException(CommandMethod commandMethod, String msg) { 23 | 24 | super(String.format("%s Offending method: %s", msg, commandMethod)); 25 | this.commandMethod = commandMethod; 26 | } 27 | 28 | /** 29 | * @return the offending {@link CommandMethod}. 30 | */ 31 | public CommandMethod getCommandMethod() { 32 | return commandMethod; 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/event/connection/JfrConnectionActivatedEvent.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.event.connection; 2 | 3 | import jdk.jfr.Category; 4 | import jdk.jfr.Event; 5 | import jdk.jfr.Label; 6 | import jdk.jfr.StackTrace; 7 | 8 | /** 9 | * Flight recorder event variant of {@link ConnectionActivatedEvent}. 10 | * 11 | * @author Mark Paluch 12 | * @since 6.1 13 | */ 14 | @Category({ "Lettuce", "Connection Events" }) 15 | @Label("Connection Activated") 16 | @StackTrace(false) 17 | class JfrConnectionActivatedEvent extends Event { 18 | 19 | private final String redisUri; 20 | 21 | private final String epId; 22 | 23 | private final String channelId; 24 | 25 | private final String local; 26 | 27 | private final String remote; 28 | 29 | public JfrConnectionActivatedEvent(ConnectionEventSupport event) { 30 | this.redisUri = event.getRedisUri(); 31 | this.epId = event.getChannelId(); 32 | this.channelId = event.getChannelId(); 33 | this.local = event.localAddress().toString(); 34 | this.remote = event.remoteAddress().toString(); 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /.github/workflows/doctests.yml: -------------------------------------------------------------------------------- 1 | name: Documentation Tests 2 | 3 | on: 4 | push: 5 | tags-ignore: 6 | - '*' 7 | branches: 8 | - 'main' 9 | pull_request: 10 | workflow_dispatch: 11 | 12 | jobs: 13 | doctests: 14 | runs-on: ubuntu-latest 15 | services: 16 | redis-stack: 17 | image: redis:8.0.2 18 | options: >- 19 | --health-cmd "redis-cli ping" --health-interval 10s --health-timeout 5s --health-retries 5 20 | ports: 21 | - 6379:6379 22 | 23 | steps: 24 | - name: Checkout project 25 | uses: actions/checkout@v4 26 | - name: Set up Java 27 | uses: actions/setup-java@v2 28 | with: 29 | java-version: '11' 30 | distribution: 'temurin' 31 | - name: Cache local Maven repository 32 | uses: actions/cache@v4 33 | with: 34 | path: ~/.m2/repository 35 | key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} 36 | restore-keys: | 37 | ${{ runner.os }}-maven- 38 | - name: Run doctests 39 | run: | 40 | mvn -Pdoctests test 41 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/dynamic/RedisCommandsMetadata.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.dynamic; 2 | 3 | import java.lang.annotation.Annotation; 4 | import java.lang.reflect.Method; 5 | import java.util.Collection; 6 | 7 | /** 8 | * Interface exposing Redis command interface metadata. 9 | * 10 | * @author Mark Paluch 11 | * @since 5.0 12 | */ 13 | interface RedisCommandsMetadata { 14 | 15 | Collection getMethods(); 16 | 17 | /** 18 | * Returns the Redis Commands interface. 19 | * 20 | * @return 21 | */ 22 | Class getCommandsInterface(); 23 | 24 | /** 25 | * Lookup an interface annotation. 26 | * 27 | * @param annotationClass the annotation class. 28 | * @return the annotation object or {@code null} if not found. 29 | */ 30 | A getAnnotation(Class annotationClass); 31 | 32 | /** 33 | * @param annotationClass the annotation class. 34 | * @return {@code true} if the interface is annotated with {@code annotationClass}. 35 | */ 36 | boolean hasAnnotation(Class annotationClass); 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/io/lettuce/core/event/connection/JfrConnectionDeactivatedEvent.java: -------------------------------------------------------------------------------- 1 | package io.lettuce.core.event.connection; 2 | 3 | import jdk.jfr.Category; 4 | import jdk.jfr.Event; 5 | import jdk.jfr.Label; 6 | import jdk.jfr.StackTrace; 7 | 8 | /** 9 | * Flight recorder event variant of {@link ConnectionDeactivatedEvent}. 10 | * 11 | * @author Mark Paluch 12 | * @since 6.1 13 | */ 14 | @Category({ "Lettuce", "Connection Events" }) 15 | @Label("Connection Deactivated") 16 | @StackTrace(false) 17 | class JfrConnectionDeactivatedEvent extends Event { 18 | 19 | private final String redisUri; 20 | 21 | private final String epId; 22 | 23 | private final String channelId; 24 | 25 | private final String local; 26 | 27 | private final String remote; 28 | 29 | public JfrConnectionDeactivatedEvent(ConnectionEventSupport event) { 30 | this.redisUri = event.getRedisUri(); 31 | this.epId = event.getChannelId(); 32 | this.channelId = event.getChannelId(); 33 | this.local = event.localAddress().toString(); 34 | this.remote = event.remoteAddress().toString(); 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023-Present, Redis Ltd. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. --------------------------------------------------------------------------------