1. 08 Mar, 2021 2 commits
    • Nathan Harris's avatar
      c8637c1f
    • Lukasa's avatar
      Add support for service discovery. · 1168ed09
      Lukasa authored
      The newly-released Service Discovery framework gives us the interesting
      opportunity to make RediStack aware of complex service discovery tools.
      This patch supplies a simple adaptor to integrat Service Discovery with
      RediStack's pooled client, allowing users to work with arbitrary service
      discovery systems.
      1168ed09
  2. 03 Mar, 2021 1 commit
    • Lukasa's avatar
      Delay connection attempts without addresses. · 338a6f4a
      Lukasa authored
      In some circumstances users may have connection pools configured without
      any SocketAddresses ready to go. This is particularly likely in service
      discovery configurations. Right now, the effect of attempting to use
      such a pool is two fold. First, we'll emit a bunch of error level logs
      telling users we have no addresses. Second, we'll fall into the
      exponential backoff phase of connection establishment.
      
      The first property is annoying, but the second one is actively harmful.
      If your construction is timed incorrectly, we'll have the awkward
      problem of burning a bunch of CPU trying to create connections we know
      we cannot, and then a lengthy delay after the addresses are actually
      configured before we start trying to use them. That's the worst of all
      worlds.
      
      This patch adds logic to detect the attempt to create connections when
      we don't have any configured addresses and delays them. This path should
      improve performance and ergonomics when in this mode.
      338a6f4a
  3. 22 Feb, 2021 1 commit
  4. 16 Feb, 2021 3 commits
  5. 07 Feb, 2021 1 commit
  6. 02 Dec, 2020 4 commits
    • Nathan Harris's avatar
      Refactor RedisCommand into a general use object · 3c671303
      Nathan Harris authored
      Motivation:
      
      RediStack today represents a command as a temporary object for the purpose of writing to the channel.
      
      While it is useful to have an object for that purpose, commands handled in this way require immediate execution
      and aren't available for other purposes.
      
      Commands can serve a better purpose as a lightweight object to support delayed execution,
      so that pipeling as described in issue #63 could be possible.
      
      Modifications:
      
      - Add: `get` overloads for JSON codable interaction on `RedisClient`
      - Add: New `RedisZRangeResultOption` type for better interactions with zrange operations that can optionally return scores
      - Add: New `RedisHashFieldKey` for type-safety when working with Hash field keys much like `RedisKey`
      - Change: A few API types from enums to structs for library evolution
      - Change: `RedisCommandHandler` to operate on a tuple of `RESPValue, EventLoopPromise<RESPValue>` rather than `RedisCommand`
      - Change: `RedisCommand` to be a generic str...
      3c671303
    • Nathan Harris's avatar
      61fb40b1
    • Nathan Harris's avatar
      Add historical test matrix to README · ba35a1f9
      Nathan Harris authored
      ba35a1f9
    • Nathan Harris's avatar
      Set Swift 5.2 as the minimum version · b1484916
      Nathan Harris authored
      b1484916
  7. 27 Nov, 2020 1 commit
    • Nathan Harris's avatar
      Rename RedisKeyLifetime to be nested in RedisKey · 8bf26fb6
      Nathan Harris authored
      Motivation:
      
      `RedisKeyLifetime` already has "RedisKey" as a prefix so it naturally fits as a nested type.
      
      Modifications:
      
      - Change: `RedisKeyLifetime` to be nested in `RedisKey` and named `Lifetime`
      - Rename: `RedisKeyLifetime.Lifetime` to `Duration`
      - Deprecate: `RedisKeyLifetime` and the nested type `Lifetime`
      
      Result:
      
      The global namespace is a little less cluttered with the types falling naturally where they already are.
      8bf26fb6
  8. 22 Nov, 2020 3 commits
  9. 18 Oct, 2020 1 commit
  10. 17 Oct, 2020 2 commits
    • Nathan Harris's avatar
      Change RedisConnection to end subscriptions when not allowed · 61cc879e
      Nathan Harris authored
      Motivation:
      
      When `RedisConnection.allowSubscriptions` is set to `false`, the connection could still be in a subscription state
      leaving further commands to fail slowly from a full roundtrip to Redis, rather than succeeding as expected.
      
      This changes the implementation so that it triggers a full unsubscribe from patterns and channels when set to `false`.
      
      Modifications:
      
      - Change: `RedisConnection.allowSubscriptions` to call `unsubscribe()` and `punsubscribe()` when set to `false`
      - Change: `RedisPubSubHandler` to prefix storage of all dictionary keys to avoid name clashes between pattern and channel subscriptions
      
      Result:
      
      Developers should now have more deterministic and unsurprising behavior with PubSub
      in regards to subscription management and connection state.
      61cc879e
    • Nathan Harris's avatar
      Fix [p]unsubscribe from all · e0d47f73
      Nathan Harris authored
      Motivation:
      
      The methods of unsubscribing from all channels / patterns were not working as expected as they need to be special-case handled.
      
      Modifications:
      
      - Change: `RedisPubSubHandler` to be special-case unsubscribe when no arguments are provided
      
      Result:
      
      Developers should now properly be able to unsubscribe from all channels / patterns with a single method call.
      e0d47f73
  11. 15 Oct, 2020 1 commit
    • Nathan Harris's avatar
      Allow repeated commands to same connection in pool · 42e8d4b1
      Nathan Harris authored
      Motivation:
      
      Some Redis commands are very connection specific that have impacts on future access that makes it difficult in the current
      checkout-use-return cycle that `RedisConnectionPool` uses.
      
      Developers need a way to borrow a specific connection, chain several commands together, and then return the connection to the pool.
      
      Modifications:
      
      - Add: `leaseConnection` method to `RedisConnectionPool` which provides a connection from the pool and returns it after a provided closure's ELF resolves
      - Add: `allowSubscriptions` property to `RedisConnection` for controlling the ability to make PubSub subscriptions
      - Add: `RedisClientError.pubsubNotAllowed` case for when `RedisConnection.allowSubscriptions` is set to `false` and a subscription was still attempted
      
      Result:
      
      Developers should now have an "escape hatch" with `RedisConnectionPool` to do limited exclusive chains of operations on a specific connection.
      42e8d4b1
  12. 07 Oct, 2020 3 commits
    • Nathan Harris's avatar
    • Nathan Harris's avatar
      Add default buffer connectionRetryTimeout to avoid literal immediate timeouts · c8cb256b
      Nathan Harris authored
      Motivation:
      
      When trying to allow users to configure the connection retry timeout offset,
      not having a value provided (deadline of `now`) caused all attempts to use the pool to fail.
      
      Modifications:
      
      - Change: RedisConnectionPool to always have a timeout offset defined
      
      Result:
      
      If users don't specify any value, then the default of 60 seconds will be used.
      
      If users specify "nil" (or `.none`) as the timeout, then a minimum of 10 milliseconds will be used to avoid immediate timeouts
      
      Otherwise, use the user's specified `TimeAmount` as the offset of the timeout
      c8cb256b
    • Nathan Harris's avatar
      Add configuration option for RedisConnectionPool lease timeout · 3e28e75b
      Nathan Harris authored
      Motivation:
      
      With RedisConnectionPool a timeout is provided to prevent infinite loops of
      retrying connections, but right now it is hardcoded to 60 seconds.
      
      Users of downstream projects such as Vapor are noticing a "regression" of sorts, as previously
      EventLoopFutures would fail immediately if a connection was not made available.
      
      Modifications:
      
      - Add: `connectionRetryTimeout` parameter to `RedisConnectionPool` initializer that still defaults to 60 seconds
      - Change: RedisConnectionPool to use the new parameter if available to offset a deadline from "now"
      
      Result:
      
      Users can now configure the connection pool to fail immediately if connections are not available.
      3e28e75b
  13. 02 Oct, 2020 1 commit
    • Nathan Harris's avatar
      Resolve PubSub post-commit feedback · e858c0a6
      Nathan Harris authored
      Motivation:
      
      To ship PubSub faster, it was merged to the master branch without a peer review. This commit is to address the critical points of feedback given in a post-commit review.
      
      Modifications:
      
      - Add: New RedisClientError case where a "race condition" of removing a pubsub handler and subscription can happen
      - Add: New state to RedisPubSubHandler for when it has been removed from a ChannelPipeline
      - Change: RedisPubSubHandler to require an `eventLoop` in its initializer
      - Change: The subscribe and unsubscribe methods on RedisPubSubHandler to handle the EventLoop hopping to be thread-safe
      
      Result:
      
      PubSub should have a more robust and thread-safe implementation.
      e858c0a6
  14. 30 Sep, 2020 1 commit
    • Nathan Harris's avatar
      Add support for PubSub · e7b597fc
      Nathan Harris authored
      Motivation:
      
      One of the great features of Redis is being able to subscribe and receive messages published to specific channels
      as a way of acting as a message queue for processing jobs.
      
      PubSub requires a specific understanding of the connection model that can only be implemented directly in this library.
      
      Modifications:
      
      - Add: `RedisPubSubHandler` to sit in front of `RedisCommandHandler` to manage subscription callbacks and Redis registration
      - Add: `publish` and the `pubsub` commands
      - Add: `addPubSubHandler` extension to `NIO.Channel`
      - Add: Type-safe String wrapper of `RedisChannelName` for PubSub methods
      - Add: `pubsubSubscriptionNotFound` error case
      - Add: `isSubscribed` property to `RedisConnection`
      - Add: `availableConnectionCount` and `leasedConnectionCount` properties to `RedisConnectionPool`
      - Add: Metrics for PubSub
      - Add: `makeNewPool` factory method to `RedisConnectionPoolIntegrationTestCase`
      - Change: `RedisClient` to require methods for PubSub management, as they are intrinsicly tied to the client's connection model
      - Change: Parsing of `PING` response for handling special case in PubSub mode
      - Rename: `ActiveConnectionGauge` to `RedisMetrics.IncrementalGauge`
      
      Result:
      
      Developers will now be able to use Redis in PubSub mode with both connections and pools.
      
      This resolves #6
      e7b597fc
  15. 18 Sep, 2020 1 commit
  16. 08 Sep, 2020 1 commit
  17. 01 Sep, 2020 2 commits
    • Nathan Harris's avatar
      Update contributors · 8fb1aed7
      Nathan Harris authored
      8fb1aed7
    • Nathan Harris's avatar
      Refactor Logging implementation · 90244e32
      Nathan Harris authored
      Motivation:
      
      The original implementation of Logging was done in more haste than should have been, without proper attention given to the semantic requirements.
      
      As the Swift ecosystem has matured a bit, lessons have been learned on handling metadata and passing of external context into internal subcomponents.
      
      A mixture of the "protocol-based context passing" and "explicit context passing" patterns have been adopted.
      
      Both patterns are more fully described in the Swift forum discussion: https://forums.swift.org/t/the-context-passing-problem/39162
      
      Modifications:
      
      - Add: `RedisLogging` namespace with references to static keys and labels that are used for Logging throughout the library
      - Add: `Logger` static computed properties to access the Logger prototypes used in connection and connection pools
      - Add: `RedisClientWithUserContext` protocol and `UserContextRedisClient` types to assist with wrapping client types for custom logger contexts
      - Remove: `logger` property from `Red...
      90244e32
  18. 30 Aug, 2020 6 commits
  19. 09 Aug, 2020 1 commit
  20. 05 Aug, 2020 1 commit
    • tanner's avatar
      Add optional promise parameter to RedisConnectionPool.close · 40d1a587
      tanner authored
      Motivation:
      
      The actual process for closing a connection pool involves closing each individual connection, which is all asynchronous.
      
      There is currently no way to work off of the event when all of the connections have completed their close process.
      
      Modifications:
      
      - Add: `poolHasActiveConnections` error value to `RedisConnectionPoolError`
      - Add: `promise` parameter to the `RedisConnectionPool.close` method
      - Add: Documentation comments for the close method
      
      Result:
      
      Developers should now have a way of chaining callbacks when all connections in a pool have been closed.
      40d1a587
  21. 02 Aug, 2020 2 commits
  22. 21 Jun, 2020 1 commit
    • Nathan Harris's avatar
      Rename ELF extension `map` to `tryConverting` and make internal · c4ff3fc3
      Nathan Harris authored
      Motivation:
      
      As originally pointed out in #48, the `map` prefix alone is not enough context into what the method actually does.
      
      Since it fails the future, and isn't a mapping function, the name should reflect this.
      
      But, this method as-is currently provides little value outside of the client context, so it should not be `public`.
      
      If users provide an adequate use case for having it outside of the package, then it can be made public again.
      
      Modifications:
      
      - Rename: ELF where Value == RESPValue extension `map` to `tryConverting`
      - Change: `tryConverting` from public to internal
      
      Result:
      
      A "problematic" method should no longer be available for API users to hurt themselves with.
      c4ff3fc3