GitLab's annual major release is around the corner. Along with a lot of new and exciting features, there will be a few breaking changes. Learn more here.

  1. 04 Jun, 2020 1 commit
    • Nathan Harris's avatar
      Convert `RESPTranslator.ParsingError` from enum to struct · b48b4729
      Nathan Harris authored
      Motivation:
      
      Much like the change for `RedisClientError` (6471a2) any error enum that we may want to change will necessitate a major SemVer.
      
      To avoid this, we need to use the established struct-as-enum pattern.
      
      Modifications:
      
      - Change: `RESPTranslator.ParsingError` to be a struct backed by an enum
      
      Result:
      
      The library should be able to evolve to add more `RESPTranslator.ParsingError` cases without becoming a breaking change.
      b48b4729
  2. 27 May, 2020 2 commits
    • Lukasa's avatar
      Detect and throw on invalid integer. · 2211dbf3
      Lukasa authored
      Motivation:
      
      parseInteger did not distinguish between not having enough bytes for an
      integer and not being able to parse the integer that was present. This
      was a bit tricky for code internally, where some call sites had extra
      code looking for spooky action at a distance in order to determine if
      the integer failed to parse.
      
      This is unnecessary: parseInteger is sufficiently aware of what's going
      on to address this problem itself.
      
      Modifications:
      
      - Added a new parser error (acceptable as we haven't tagged 1.0 yet).
      - Throw it from parseInteger if the integer is invalid.
      
      Result:
      
      parseInteger clearly communicates if the integer failed to parse.
      2211dbf3
    • Lukasa's avatar
      Clean up indexing of ByteBufferView · 638fbb07
      Lukasa authored
      Motivation:
      
      ByteBufferView is not zero indexed, but parseSimpleString assumes it is.
      
      Modifications:
      
      - Correctly compute on the distance between two indices.
      - New, somewhat contrived, test case.
      
      Result:
      
      No functional change: because RediStack assumes the remote peer will
      always correctly terminate with /r/n, there is no point at which this
      code could misbehave in the current implementation. However, with small
      changes it is possible to trigger it, as the new test demonstrates.
      638fbb07
  3. 26 May, 2020 2 commits
    • Lukasa's avatar
      Avoid creating temporary arrays · f9579373
      Lukasa authored
      Motivation:
      
      When we only want the first byte, rather than create temporary
      intermediate arrays we can just ask NIO to give us the first byte. This
      avoids unnecessary allocations.
      
      Modifications:
      
      - Replace `readBytes(length: 1).first` with `readInteger(as:
        UInt8.self)`
      
      Results:
      
      11% performance improvement in load testing due to reduced allocator
      pressure on the hot path.
      f9579373
    • Lukasa's avatar
      Avoid transient ByteBufferView · dd086855
      Lukasa authored
      Motivation:
      
      When attempting to locate a single byte, creating a transient
      ByteBufferView is an excessively heavyweight operation compared to a
      simple getInteger. In particular, a BBV requires retain/release
      operations to enforce the CoW invariants, as well as requires jumps
      through substantial amounts of generic Collection code. While this can
      be specialized, so can getInteger, and getInteger has much less code in
      the way to cause costs.
      
      Modifications:
      
      - Replace temporary view creation with getInteger.
      
      Results:
      
      5% performance improvement on raw throughput tests.
      dd086855
  4. 29 Jul, 2019 1 commit
    • Nathan Harris's avatar
      Add more test coverage of `RESPTranslator` · b9b70307
      Nathan Harris authored
      Motivation:
      
      Diagnostics for why `.bulkString` parses might fail were weak, and edge cases fell through gaps in coverage were found.
      
      Modifications:
      
      Added new cases to `RESPTranslator.ParsingError` for `.bulkString` parsing with additional test coverage.
      
      Result:
      
      Users should have better diagnostics for bogus data or failed parsing state.
      b9b70307
  5. 09 Jul, 2019 1 commit
  6. 03 Jul, 2019 2 commits
    • Nathan Harris's avatar
      Revisit `RESPValue` and `RESPValueConvertible` implementations. · cd9bd04f
      Nathan Harris authored
      Motivation:
      
      Johannes provided a fair code review of the project and summarized his findings in issue #48, and one of the prime offenders was all of the `unsafe*` APIs (pointers, buffers, bytes)
      that were used with `RESPValue` and `RESPValueConvertible`.
      
      He also provided great feedback and pointed out good points of confusion with the API design of `RESPValue` and `RESPValueConvertible`.
      
      Modifications:
      
      - Return to using `Array` instead of `ContiguousArray` for `RESPValue.array` storage
      - Update all documentation to be more thorough in explaining how the types should be used and conformed to.
      - Remove all uses of `unsafe*` APIs where possible
      - Change implementations to be a lot more type and memory safe, double checking assumptions
      - Remove conformance to `ExpressibleBy*Literal` as it is too easy for users to shoot themselves in the foot and saves only a few characters over `.init(bulk:)`
      - Create new `RedisNIOTestUtils` target for common test extensions, making them public
      - Move most almost all implementations of `RESPValue` computed properties into the `RESPValueConvertible` conformances
      
      Result:
      
      Users should be more safeguarded by the API against unknowingly getting incorrect `RESPValue` representations, the API design of `RESPValue` and `RESPValueConvertible` should be much clearer,
      and memory safety should be at a higher bar from these changes.
      
      This resolves issues #55 & #48, and contributes to issue #47.
      cd9bd04f
    • Nathan Harris's avatar
      Refactor `RESPTranslator` to mutate the passed `ByteBuffer` directly. · b8c19488
      Nathan Harris authored
      Motivation:
      
      During proposal review, it was pointed out that the code with a position index was redundant and error prone over relying on `ByteBuffer`'s `readerIndex`.
      
      Modifications:
      
      Refactored `RESPTranslator` to rely on `ByteBuffer.readerIndex` for position of current parsing cursor,
      and eliminated `ParsingResult` enum to instead return `RESPValue?`.
      
      The implementation for writing out `RESPValue` has been expanded to `RESPValueConvertible` and moved to an extension of `ByteBuffer`.
      
      Result:
      
      Parsing `RESPValue` into and out of `ByteBuffer` should be less error-prone and more straight forward.
      
      This contributes to issues #47 and #55
      b8c19488
  7. 22 Jun, 2019 1 commit
  8. 06 Jun, 2019 1 commit
    • Nathan Harris's avatar
      Rename `NIORedis` to `RedisNIO` · e81f9546
      Nathan Harris authored
      Motivation:
      
      The SSWG has identified a fast approaching reality of namespace clashes in SPM within the ecosystem and has proposed a rule on names that `NIORedis` no longer complies with.
      
      Modifications:
      
      All references to `NIORedis` have been switched to `RedisNIO` as this module name is unique (at least within GitHub's public repositories).
      
      The goals for this name are as follows:
      
      1. To indicate that this is a Redis client library that is built with SwiftNIO
      2. That it is a lower level library, as it directly exposes SwiftNIO as an implementation detail
          2a. The idea being that a higher level library (`Redis`) will be used, and to "go one level deeper" in the stack, you append the "deeper" `NIO` postfix
      3. It follows a naming pattern adopted by Vapor who has expressed their desire to adopt this library as their Redis implementation
      
      Result:
      
      A repository, package name, and module name that are unique across GitHub's public repositories that achives the goals outlined above.
      e81f9546
  9. 02 May, 2019 1 commit
  10. 01 May, 2019 2 commits
    • Nathan Harris's avatar
    • Nathan Harris's avatar
      Simplify RESP Parsing and Redis Channel Handlers · 477668e6
      Nathan Harris authored
      Motivation:
      
      As it stands, the parsing / encoding implementations for RESP was directly tied to the NIO Channel Handlers.
      
      Unit tests were sloppily spread across multiple files and it made it difficult to explicitly separate out
      the Channel Handler behavior from the RESP specification implementation.
      
      Modifications:
      
      - Add: `RESPTranslator` enum helper object with static methods that only handles RESP parsing / encoding
      - Rename: `RESPEncoder` to `RedisMessageEncoder`
      - Rename: `RESPDecoder` to `RedisByteDecoder`
      
      Results:
      
      It should be easier to understand what type is intended to be used as part of a NIO channel pipeline while
      still having a direct way of parsing / encoding between Swift types and the RESP specification.
      
      Unit tests should be more maintainable as well.
      477668e6
  11. 30 Apr, 2019 1 commit
    • Nathan Harris's avatar
      Standardize Error Handling · 46e96bd9
      Nathan Harris authored
      Motivation:
      
      `RedisError` was being used in many places in an ad-hoc fashion that made it unclear as to what source of errors it exactly represents.
      
      In addition, it doesn't follow community conventions of handling known "classes" of errors with enums rather than static struct instances.
      
      Results:
      
      All errors that are generated and thrown within the library are specified as either `RESPDecoder.Error` or `NIORedisError`.
      
      `RedisError` is simplified to represent an error message sent by a Redis instance that conforms to `LocalizedError`.
      46e96bd9
  12. 09 Apr, 2019 1 commit
    • Nathan Harris's avatar
      Rework RESPValue to use ByteBuffers for .simpleString and .bulkString · d93511b8
      Nathan Harris authored
      Motivation:
      
      Throughout the process of creating and using RESPValue, many unnecessary allocations happened translating ByteBuffers into [Int8] raw byte arrays.
      
      Results:
      
      RESPValue has a more conherent underlying data structure and computed properties, while decoding RESP is more straight forward and performant
      
      Resolves #31
      d93511b8
  13. 01 Apr, 2019 1 commit
    • Nathan Harris's avatar
      Replace `Foundation.Data` with `[UInt8]` type everywhere · 3c53d440
      Nathan Harris authored
      Motivation:
      
      `Foundation.Data` is known to be more expensive than is necessary for this low level of a library, and has some quirks with its usage.
      
      Results:
      
      This library now works with byte arrays (`[UInt8]`) directly, and all references to `Foundation` now explicitly import the exact types they need.
      3c53d440
  14. 12 Mar, 2019 1 commit
    • Nathan Harris's avatar
      Housekeeping of code · 571d7bce
      Nathan Harris authored
      - Move: `String.convertedToData()` to `NIORedisTests` as a test utility
      - Change: URLs in code comments to be Markdown links
      - Change: Code comments to be more correct
      571d7bce
  15. 11 Feb, 2019 1 commit
  16. 17 Jan, 2019 1 commit
  17. 09 Jan, 2019 2 commits
  18. 22 Dec, 2018 2 commits
  19. 19 Dec, 2018 1 commit
  20. 15 Dec, 2018 6 commits
  21. 14 Dec, 2018 3 commits
  22. 13 Dec, 2018 3 commits