<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Redis on Ricky</title><link>https://5b54be02.linzeyan.pages.dev/tags/redis/</link><description>Recent content in Redis on Ricky</description><generator>Hugo -- gohugo.io</generator><language>en</language><lastBuildDate>Fri, 11 Sep 2026 08:23:01 +0800</lastBuildDate><atom:link href="https://5b54be02.linzeyan.pages.dev/tags/redis/index.xml" rel="self" type="application/rss+xml"/><item><title>Til</title><link>https://5b54be02.linzeyan.pages.dev/posts/2026/20260911-til/</link><pubDate>Fri, 11 Sep 2026 08:23:01 +0800</pubDate><guid>https://5b54be02.linzeyan.pages.dev/posts/2026/20260911-til/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://www.checklist.design/" target="_blank" rel="noopener">Checklist Design&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://tuxedono2.com/" target="_blank" rel="noopener">Tuxedo No.2 - A Cocktail Companion&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://mangamillion.shueisha.co.jp/" target="_blank" rel="noopener">MangaMillion&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://debloat.dev/" target="_blank" rel="noopener">debloat.dev — replace the junk&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://metawilo.com/" target="_blank" rel="noopener">台灣罪犯圖鑑&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://bsb.kh.edu.tw/" target="_blank" rel="noopener">直轄市及各縣市短期補習班資訊管理系統&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://coach-case-tracker.thinkingpower-office.workers.dev/" target="_blank" rel="noopener">各運動種類不適任教練名單 — 案源比對工作表&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://www.sports.gov.tw/News/6295" target="_blank" rel="noopener">運動部 - 涉及違法事件不適任教練資訊專區&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://www.sports.gov.tw/CoachDatas/6357" target="_blank" rel="noopener">運動部 - 教練證照查詢系統&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://crc.sfaa.gov.tw/ChildYoungLaw/Sanction?AspxAutoDetectCookieSupport=1" target="_blank" rel="noopener">CRC 聯合國兒童權利公約資訊網 - 違反兒少法&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://ma.mohw.gov.tw/Accessibility/VIOSearch/MASearchVIO" target="_blank" rel="noopener">衛生福利部 - 醫事人員性別事件資訊專區&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://ap.ece.moe.edu.tw/webecems/punishSearch.aspx" target="_blank" rel="noopener">全國教保資訊網 - 裁罰紀錄查詢&lt;/a>&lt;/li>
&lt;li>&lt;strong>Article&lt;/strong>
&lt;ul>
&lt;li>&lt;a href="https://shopify.engineering/scaling-inventory-reservations" target="_blank" rel="noopener">We replaced Redis with MySQL for inventory reservations—and it scaled&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://tailscale.com/blog/sqlite-wal-reset-bug" target="_blank" rel="noopener">How we tracked down a 16-year-old SQLite bug&lt;/a>&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;strong>Database&lt;/strong>
&lt;ul>
&lt;li>&lt;a href="https://github.com/vlcn-io/cr-sqlite" target="_blank" rel="noopener">cr-sqlite - Convergent, Replicated, SQLite&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/amacneil/dbmate" target="_blank" rel="noopener">Dbmate is a database migration tool that will keep your database schema in sync across multiple developers and your production servers.&lt;/a>&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;strong>Diagram&lt;/strong>
&lt;ul>
&lt;li>&lt;a href="https://github.com/tt-a1i/archify" target="_blank" rel="noopener">Turn a codebase or system description into a polished, interactive system map — directly in chat.&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/cathrynlavery/diagram-design" target="_blank" rel="noopener">Editorial diagrams your designer won&amp;rsquo;t hate.&lt;/a>&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;strong>Github&lt;/strong>
&lt;ul>
&lt;li>&lt;a href="https://github.com/drumih/turbo-fieldfare" target="_blank" rel="noopener">Gemma 4 26B-A4B inference in ~2 GB of RAM on any M-series MacBook&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/liaohch3/claude-tap" target="_blank" rel="noopener">claude-tap is a local proxy and trace viewer for AI coding agents.&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/Finb/Bark" target="_blank" rel="noopener">Bark is an iOS App which allows you to push custom notifications to your iPhone&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/darrylmorley/whatcable" target="_blank" rel="noopener">macOS menu bar app that tells you, in plain English, what each USB-C cable plugged into your Mac can actually do&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/img2threejs/img2threejs" target="_blank" rel="noopener">Rebuild the object in a reference image as a code-only, procedural Three.js model.&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/darama22/Malware-Research-Hub" target="_blank" rel="noopener">MALWARE RESEARCH HUB&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/Pumpkin-MC/Pumpkin" target="_blank" rel="noopener">Pumpkin is a Minecraft server built entirely in Rust, offering a fast, efficient, and customizable experience.&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/LodyAI/Lody" target="_blank" rel="noopener">Lody: A shared workspace for the coding agents your team already uses.&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/Lakr233/vphone-cli" target="_blank" rel="noopener">Boot a virtual iPhone via Apple&amp;rsquo;s Virtualization.framework using PCC research VM infrastructure.&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/uiverse-io/galaxy" target="_blank" rel="noopener">The largest Open-Source UI Library! Community-made and free to use. Made with either CSS or Tailwind.&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/galaxyproject/galaxy" target="_blank" rel="noopener">Data intensive science for everyone.&lt;/a>&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;strong>MCP&lt;/strong>
&lt;ul>
&lt;li>&lt;a href="https://github.com/dmtrKovalenko/fff" target="_blank" rel="noopener">fff: A file search toolkit for humans and AI agents.&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/colbymchenry/codegraph" target="_blank" rel="noopener">Pre-indexed code knowledge graph, auto syncs on code changes.&lt;/a>&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;strong>Present&lt;/strong>
&lt;ul>
&lt;li>&lt;a href="https://github.com/hugohe3/ppt-master" target="_blank" rel="noopener">PPT Master — AI generates native PowerPoint from any document&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/nyblnet/bento" target="_blank" rel="noopener">Bento — the office suite that fits in a file&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/1weiho/open-slide" target="_blank" rel="noopener">The slide framework built for agents.&lt;/a>&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;strong>Self-Hosted&lt;/strong>
&lt;ul>
&lt;li>&lt;a href="https://github.com/fabriziosalmi/certmate" target="_blank" rel="noopener">CertMate - Certificate Lifecycle Management&lt;/a>&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;strong>Skill&lt;/strong>
&lt;ul>
&lt;li>&lt;a href="https://github.com/emilkowalski/skills" target="_blank" rel="noopener">Skills for Designers and Engineers.&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/dotnet/skills/blob/main/plugins/dotnet-test/agents/code-testing-generator.agent.md" target="_blank" rel="noopener">Test Generator Agent&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/mattpocock/skills" target="_blank" rel="noopener">Skills for Real Engineers. Straight from my .agents directory.&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/htdt/godogen" target="_blank" rel="noopener">Autonomous game development for Godot, Bevy, and Babylon.js with Claude Code and Codex&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/leonxlnx/taste-skill" target="_blank" rel="noopener">Taste-Skill - gives your AI good taste. stops the AI from generating boring, generic slop&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/Emily2040/seedance-2.0" target="_blank" rel="noopener">Comprehensive production pipeline for quad-modal AI filmmaking with Seedance 2.0&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://github.com/dexhunter/seedance2-skill" target="_blank" rel="noopener">skill to create best prompts for generating videos with seedance2.0&lt;/a>&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul></description></item><item><title>Go Practical Guide: Execute Lua Scripts with go-redis</title><link>https://5b54be02.linzeyan.pages.dev/posts/2025/20250722-go-redis-lua/</link><pubDate>Tue, 22 Jul 2025 16:56:00 +0800</pubDate><guid>https://5b54be02.linzeyan.pages.dev/posts/2025/20250722-go-redis-lua/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://www.liwenzhou.com/posts/Go/go-redis-lua/" target="_blank" rel="noopener">Go Practical Guide: Execute Lua Scripts with go-redis&lt;/a>&lt;/li>
&lt;/ul>
&lt;ol>
&lt;li>Redis command &lt;code>Eval&lt;/code>&lt;/li>
&lt;li>Redis package &lt;code>redis.NewScript&lt;/code>, &lt;code>script.Run&lt;/code>&lt;/li>
&lt;/ol></description></item><item><title>OpenResty + Redis: Block High-Frequency IPs</title><link>https://5b54be02.linzeyan.pages.dev/posts/2019/20190627-openrestyredis/</link><pubDate>Thu, 27 Jun 2019 11:18:46 +0800</pubDate><guid>https://5b54be02.linzeyan.pages.dev/posts/2019/20190627-openrestyredis/</guid><description>&lt;ul>
&lt;li>&lt;a href="https://www.centos.bz/2018/11/openrestyredis%E6%8B%A6%E6%88%AA%E9%AB%98%E9%A2%91%E8%AE%BF%E9%97%AEip/" target="_blank" rel="noopener">OpenResty + Redis: Block High-Frequency IPs&lt;/a>&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-nginx" data-lang="nginx">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">init_by_lua_block&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">redis&lt;/span> = &lt;span style="color:#e6db74">require&lt;/span> &lt;span style="color:#e6db74">&amp;#34;redis&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#e6db74">client&lt;/span> = &lt;span style="color:#e6db74">redis.connect(&amp;#39;127.0.0.1&amp;#39;,&lt;/span> &lt;span style="color:#ae81ff">6379&lt;/span>&lt;span style="color:#e6db74">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#960050;background-color:#1e0010">}&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#e6db74">server&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">listen&lt;/span> &lt;span style="color:#ae81ff">8080&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">location&lt;/span> &lt;span style="color:#e6db74">/&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">access_by_lua_file&lt;/span> &lt;span style="color:#e6db74">/usr/local/nginx/conf/lua/block.lua&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">proxy_pass&lt;/span> &lt;span style="color:#e6db74">http://192.168.1.102:8000&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-lua" data-lang="lua">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">-- Redis-based IP rate limiting / blocking for OpenResty (ngx_lua)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">-- NOTE:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">-- This script assumes a global `client` variable is used/stored.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">-- Make sure `redis` module is available and `client` is initialized somewhere.&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">local&lt;/span> &lt;span style="color:#66d9ef">function&lt;/span> &lt;span style="color:#a6e22e">isConnected&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> client:ping()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">end&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">local&lt;/span> &lt;span style="color:#66d9ef">function&lt;/span> &lt;span style="color:#a6e22e">createRedisConnection&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> redis.connect(&lt;span style="color:#e6db74">&amp;#34;127.0.0.1&amp;#34;&lt;/span>, &lt;span style="color:#ae81ff">6379&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">end&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">-- If the Redis connection fails, stop blocking (allow traffic)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">if&lt;/span> pcall(isConnected) &lt;span style="color:#66d9ef">then&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">-- already connected (or ping succeeded)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">else&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">-- not connected; try reconnect&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> pcall(createRedisConnection) &lt;span style="color:#66d9ef">then&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">-- Reconnect: this will reconnect Redis on every request&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">-- For high traffic, consider disabling reconnect (skip pcall), and allow/terminate directly via ngx.exit&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> client &lt;span style="color:#f92672">=&lt;/span> createRedisConnection()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">else&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ngx.exit(ngx.OK)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">end&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">end&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">local&lt;/span> ttl &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">60&lt;/span> &lt;span style="color:#75715e">-- sampling window (seconds)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">local&lt;/span> bktimes &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">30&lt;/span> &lt;span style="color:#75715e">-- requests within window to trigger block&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">local&lt;/span> block_ttl &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">600&lt;/span> &lt;span style="color:#75715e">-- block duration after trigger (seconds)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">local&lt;/span> ip &lt;span style="color:#f92672">=&lt;/span> ngx.var.remote_addr
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">local&lt;/span> ipvtimes &lt;span style="color:#f92672">=&lt;/span> client:get(ip)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">if&lt;/span> ipvtimes &lt;span style="color:#66d9ef">then&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> ipvtimes &lt;span style="color:#f92672">==&lt;/span> &lt;span style="color:#e6db74">&amp;#34;-1&amp;#34;&lt;/span> &lt;span style="color:#66d9ef">then&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">-- blocked&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> ngx.exit(&lt;span style="color:#ae81ff">403&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">else&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">local&lt;/span> last_ttl &lt;span style="color:#f92672">=&lt;/span> client:ttl(ip)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">-- ngx.say(&amp;#34;key exist.ttl is &amp;#34;, last_ttl)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> last_ttl &lt;span style="color:#f92672">==&lt;/span> &lt;span style="color:#f92672">-&lt;/span>&lt;span style="color:#ae81ff">1&lt;/span> &lt;span style="color:#66d9ef">then&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> client:set(ip, &lt;span style="color:#ae81ff">0&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> client:expire(ip, ttl)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">-- ngx.say(&amp;#34;ttl &amp;amp; vtimes recount&amp;#34;)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> ngx.exit(ngx.OK)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">end&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">local&lt;/span> vtimes &lt;span style="color:#f92672">=&lt;/span> tonumber(client:get(ip)) &lt;span style="color:#f92672">+&lt;/span> &lt;span style="color:#ae81ff">1&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> vtimes &lt;span style="color:#f92672">&amp;lt;&lt;/span> bktimes &lt;span style="color:#66d9ef">then&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> client:set(ip, vtimes)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> client:expire(ip, last_ttl)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">-- ngx.say(ip, &amp;#34; view &amp;#34;, vtimes, &amp;#34; times&amp;#34;)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> ngx.exit(ngx.OK)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">else&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">-- ngx.say(ip, &amp;#34; will be block next time.&amp;#34;)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> client:set(ip, &lt;span style="color:#f92672">-&lt;/span>&lt;span style="color:#ae81ff">1&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> client:expire(ip, block_ttl)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> ngx.exit(ngx.OK)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">end&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">end&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">else&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">-- key does not exist&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> client:set(ip, &lt;span style="color:#ae81ff">1&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">-- ngx.say(ip, &amp;#34; view 1 times&amp;#34;)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> client:expire(ip, ttl)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> ngx.exit(ngx.OK)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">end&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item></channel></rss>