redis
redis copied to clipboard
Allow keyed cache access without `data` wrapper via `KeyedCacheSupporting`
The KeyedCacheSupporting
implementation wraps all Codable
values in a data
object.
I can see why this is needed for String
, Int
, etc, when using Codable
with JSON.
However, when getting data from a redis cache that is shared with different (non-vapor) services, I'd like to be able to skip the data
wrapper and still use Codable
for my own objects.
Is there a way to get or set Codable
values without this data wrapper and still use keyed cache API?
let cache = try req.keyedCache(for: .redis)
return cache.get("my-key", as: MyModel.self)
My current workaround is to get raw values using the RedisClient
directly:
req.withPooledConnection(to: .redis) { redis in
redis.jsonGet("my-key", as: MyModel.self)
}
Here is the current KeyedCacheSupporting
implementation that uses the data
wrapper:
extension RedisDatabase: KeyedCacheSupporting {
/// See `KeyedCacheSupporting`.
public static func keyedCacheGet<D>(_ key: String, as decodable: D.Type, on conn: RedisClient) throws -> EventLoopFuture<D?> where D : Decodable {
return conn.jsonGet(key, as: _DWrapper<D>.self).map { $0?.data }
}
/// See `KeyedCacheSupporting`.
public static func keyedCacheSet<E>(_ key: String, to encodable: E, on conn: RedisClient) throws -> EventLoopFuture<Void> where E : Encodable {
return conn.jsonSet(key, to: _EWrapper(encodable))
}
/// See `KeyedCacheSupporting`.
public static func keyedCacheRemove(_ key: String, on conn: RedisClient) throws -> EventLoopFuture<Void> {
return conn.delete(key)
}
}
private struct _EWrapper<T>: Encodable where T: Encodable {
var data: T
init(_ data: T) { self.data = data }
}
private struct _DWrapper<T>: Decodable where T: Decodable {
var data: T
init(_ data: T) { self.data = data }
}
No, that's not possible with the current API. As you mentioned, we must wrap everything because Swift's JSON coders don't support top-level fragments. The workaround you found seems like the best option.
I think it's worth trying to find a better solution here, but that would need to be targeted to the next release. Some ideas:
- Find a workaround to en/decoding top-level JSON fragments. (I like this the best)
- Only wrap values if they are single value.
Awesome. Thanks @tanner0101.
The workaround is pretty usable for now 👍