Skip to content

Allow keyed cache access without data wrapper via KeyedCacheSupporting #140

Description

@wlisac

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 }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions