class AbstractRedisRateLimiter implements RedisRateLimiter<List<Long>> {

    private static final String SCRIPT_PATH = "/scripts/";

    protected static final String PREFIX = "dtp";

    private final RedisScript<List<Long>> script;

    protected final StringRedisTemplate stringRedisTemplate;

    protected static final AtomicInteger COUNTER = new AtomicInteger(0);

    public AbstractRedisRateLimiter(String scriptName, StringRedisTemplate stringRedisTemplate) {
        DefaultRedisScript redisScript = new DefaultRedisScript<>();
        redisScript.setScriptSource(new ResourceScriptSource(new ClassPathResource(SCRIPT_PATH + scriptName)));
        redisScript.setResultType(List.class);
        this.script = redisScript;
        this.stringRedisTemplate = stringRedisTemplate;
    }

    @Override
    public RedisScript<List<Long>> getScript() {
        return script;
    }

    @Override
    public List<String> getKeys(final String key) {
        String cacheKey = PREFIX + ":" + key;
        return Collections.singletonList(cacheKey);
    }

    @Override
    public List<Long> isAllowed(String key, long windowSize, int limit) {<FILL_FUNCTION_BODY>}

    private String doubleToString(final double param) {
        return String.valueOf(param);
    }
}

        RedisScript<?> script = this.getScript();
        List<String> keys = this.getKeys(key);

        return Collections.unmodifiableList((List) Objects.requireNonNull(stringRedisTemplate.execute(script, keys,
                doubleToString(windowSize), doubleToString(limit), doubleToString(Instant.now().getEpochSecond()))));
    
<no_super_class>