class ReactiveRedisLock extends AbstractSimpleLock {
        private final String key;
        private final ReactiveStringRedisTemplate redisTemplate;

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

        private static String createValue(Instant now) {
            return String.format("ADDED:%s@%s", toIsoString(now), getHostname());
        }

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

        @Override
        protected void doUnlock() {<FILL_FUNCTION_BODY>}
    }

            Instant now = ClockProvider.now();
            Duration expirationTime = Duration.between(now, lockConfiguration.getLockAtLeastUntil());
            if (expirationTime.isNegative() || expirationTime.isZero()) {
                try {
                    redisTemplate.delete(key).block();
                } catch (Exception e) {
                    throw new LockException("Can not remove node", e);
                }
            } else {
                String value = createValue(now);
                redisTemplate
                        .opsForValue()
                        .setIfPresent(key, value, expirationTime)
                        .block();
            }
        
<no_super_class>