class RedisLock extends AbstractSimpleLock {

        private final String key;
        private final StringRedisTemplate redisTemplate;

        private RedisLock(String key, StringRedisTemplate redisTemplate, LockConfiguration lockConfiguration) {
            super(lockConfiguration);
            this.key = key;
            this.redisTemplate = redisTemplate;
        }

        @Override
        public void doUnlock() {
            Expiration keepLockFor = getExpiration(lockConfiguration.getLockAtLeastUntil());
            // lock at least until is in the past
            if (keepLockFor.getExpirationTimeInMilliseconds() <= 0) {
                try {
                    redisTemplate.delete(key);
                } catch (Exception e) {
                    throw new LockException("Can not remove node", e);
                }
            } else {
                tryToSetExpiration(this.redisTemplate, key, keepLockFor, SetOption.SET_IF_PRESENT);
            }
        }
    }

    String buildKey(String lockName) {
        return String.format("%s:%s:%s", keyPrefix, environment, lockName);
    }

    private static Boolean tryToSetExpiration(
            StringRedisTemplate template, String key, Expiration expiration, SetOption option) {<FILL_FUNCTION_BODY>

        return template.execute(
                connection -> {
                    byte[] serializedKey = ((RedisSerializer<String>) template.getKeySerializer()).serialize(key);
                    byte[] serializedValue = ((RedisSerializer<String>) template.getValueSerializer())
                            .serialize(String.format("ADDED:%s@%s", toIsoString(ClockProvider.now()), getHostname()));
                    return connection.set(serializedKey, serializedValue, expiration, option);
                },
                false);
    
<no_super_class>