Category: Uncategorized

  • WordPress Transients: The Hidden Pitfall of Lazy Garbage Collection

    WordPress Transients: The Hidden Pitfall of Lazy Garbage Collection

    What are Transients?

    WordPress transients are a simple way to cache data with an expiration time. They’re designed to store temporary data that’s expensive to
    regenerate:

    // Store data for 5 minutes
    set_transient( 'my_cache_key', $data, 5 * MINUTE_IN_SECONDS );
    // Retrieve it later
    $data = get_transient( 'my_cache_key' );

    On sites with a persistent object cache (Redis, Memcached), transients are stored in memory and automatically expire. But on sites without
    an object cache, transients are stored in the wp_options table.

    The Pitfall: Lazy Garbage Collection

    Here’s what most developers don’t realize: WordPress only deletes expired transients when you call get_transient() on that specific
    transient.

    This works fine for static cache keys:

    set_transient( 'my_plugin_settings', $settings, HOUR_IN_SECONDS );
    // Later calls to get_transient( 'my_plugin_settings' ) will clean up expired data

    But it becomes a problem with dynamic cache keys:

    $cache_key = 'api_response_' . md5( $endpoint . $user_id . $date_range );
    set_transient( $cache_key, $response, 5 * MINUTE_IN_SECONDS );

    When the parameters change, you create a new transient with a different key. The old transient expires but is never accessed again, so
    it’s never deleted. Over time, thousands of orphaned transients accumulate in wp_options, causing database bloat.

    The Solution: Proactive Cleanup

    Add a scheduled cleanup job that periodically purges expired transients with your prefix:

    // Register the cron event on plugin activation
    register_activation_hook( FILE, function() {
    if ( ! wp_next_scheduled( 'my_plugin_cleanup_transients' ) ) {
    wp_schedule_event( time(), 'daily', 'my_plugin_cleanup_transients' );
    }
    });
    
    // Clean up on deactivation
    register_deactivation_hook( FILE, function() {
    wp_clear_scheduled_hook( 'my_plugin_cleanup_transients' );
    });
    
    // The cleanup function
    add_action( 'my_plugin_cleanup_transients', function() {
    global $wpdb;
    
      // Only run cleanup if not using external object cache
      if ( wp_using_ext_object_cache() ) {
          return;
      }
    
      // Delete expired transients with our prefix
      $wpdb->query(
          $wpdb->prepare(
              "DELETE a, b FROM {$wpdb->options} a
              LEFT JOIN {$wpdb->options} b ON b.option_name = CONCAT('_transient_timeout_', SUBSTRING(a.option_name, 12))
              WHERE a.option_name LIKE %s
              AND b.option_value < %d",
              $wpdb->esc_like( '_transient_my_plugin_cache_' ) . '%',
              time()
          )
      );
    
    });

    Key Takeaways

    1. Transients with dynamic keys are dangerous on sites without persistent object cache
    2. Always implement cleanup if you’re creating transients with variable cache keys
    3. Consider alternatives like storing cache in post meta (for post-specific data) or using a bounded cache with fixed slots
    4. Check wp_using_ext_object_cache() to conditionally adjust your caching strategy
  • Forwarding a Secure Enclave SSH Agent Over Tailscale

    Forwarding a Secure Enclave SSH Agent Over Tailscale

    Disclaimer: This post demonstrates that forwarding a Secure Enclave SSH agent is possible—not that you should do it. Exposing your SSH agent over a network increases your attack surface. If your Mac is compromised or the connection is intercepted, an attacker could use your keys to authenticate as you. Proceed with caution and understand the risks.

    When working remotely, you might need to use SSH keys stored in your MacBook Pro’s Secure Enclave from a remote server. Since Secure Enclave private keys cannot be exported—they never leave the hardware—forwarding your local SSH agent socket is the only way to use them from another machine.

    This guide assumes:

    • Both machines are on the same Tailscale network
    • You’re connecting from the remote server to your Mac

    Setting Up Tailscale

    Tailscale creates a private mesh network between your devices, making it easy to connect to your Mac from anywhere without exposing it to the public internet. Install Tailscale on both your Mac and the remote server, sign in with the same account, and they’ll be able to reach each other via stable 100.x.x.x IPs.

    Enabling SSH on macOS

    By default, macOS doesn’t accept incoming SSH connections. You need to enable Remote Login.

    Via System Settings

    1. Open System SettingsGeneralSharing
    2. Enable Remote Login
    3. Choose “Allow access for” (all users or specific users)

    Via command line

    sudo systemsetup -setremotelogin on
    

    Verify it’s running:

    sudo systemsetup -getremotelogin
    

    Restrict to Tailscale only (recommended)

    Edit /etc/ssh/sshd_config and add:

    ListenAddress 100.x.x.x
    

    Replace with your Mac’s Tailscale IP, then restart:

    sudo launchctl stop com.openssh.sshd
    sudo launchctl start com.openssh.sshd
    

    This prevents your Mac from accepting SSH connections from any network other than Tailscale.

    Setting Up a Secure Enclave SSH Agent

    macOS’s built-in ssh-agent doesn’t support Secure Enclave keys directly. You’ll need a third-party agent like Secretive.

    Install Secretive

    brew install --cask secretive
    

    Generate a Secure Enclave key

    1. Open Secretive
    2. Click the + button to create a new key
    3. Choose “Secure Enclave” as the store
    4. Copy the public key to your servers’ ~/.ssh/authorized_keys

    Configure SSH to use Secretive

    Add to ~/.ssh/config on your Mac:

    Host *
        IdentityAgent /Users/YOUR_USER/Library/Containers/com.maxgoedjen.Secretive.SecretAgent/Data/socket.ssh
    

    Or export the socket path:

    export SSH_AUTH_SOCK=/Users/YOUR_USER/Library/Containers/com.maxgoedjen.Secretive.SecretAgent/Data/socket.ssh
    

    Verify it’s working:

    ssh-add -l
    

    Note the socket path—you’ll need it for the forwarding commands below.

    Solution 1: SSH Local Forwarding

    The simplest approach—forward the socket through an SSH connection.

    From the remote server, connect to your Mac with -L:

    ssh -L /tmp/agent.sock:/Users/YOUR_USER/Library/Containers/com.maxgoedjen.Secretive.SecretAgent/Data/socket.ssh user@your-mac.tailnet
    

    In a separate terminal on the remote server:

    export SSH_AUTH_SOCK=/tmp/agent.sock
    ssh-add -l  # Verify it works
    

    The socket only exists while the SSH connection is open.

    Make it persistent

    Add to your shell profile on the remote server:

    export SSH_AUTH_SOCK=/tmp/agent.sock
    

    Use tmux or screen to keep the SSH session alive, or set up autossh:

    autossh -M 0 -f -N -L /tmp/agent.sock:/Users/YOUR_USER/Library/Containers/com.maxgoedjen.Secretive.SecretAgent/Data/socket.ssh user@your-mac.tailnet
    

    Solution 2: socat Over Tailscale

    Expose the socket directly over the Tailscale network using socat. No persistent SSH session required.

    On your MacBook Pro

    socat TCP-LISTEN:22122,bind=100.x.x.x,fork,reuseaddr UNIX-CONNECT:/Users/YOUR_USER/Library/Containers/com.maxgoedjen.Secretive.SecretAgent/Data/socket.ssh
    

    Replace 100.x.x.x with your Mac’s Tailscale IP and YOUR_USER with your username.

    On the remote server

    socat UNIX-LISTEN:/tmp/agent.sock,fork TCP:100.x.x.x:22122 &
    export SSH_AUTH_SOCK=/tmp/agent.sock
    ssh-add -l  # Verify it works
    

    Run as a launch agent (macOS)

    Create ~/Library/LaunchAgents/com.user.ssh-agent-relay.plist:

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
    <plist version="1.0">
    <dict>
        <key>Label</key>
        <string>com.user.ssh-agent-relay</string>
        <key>ProgramArguments</key>
        <array>
            <string>/opt/homebrew/bin/socat</string>
            <string>TCP-LISTEN:22122,bind=100.x.x.x,fork,reuseaddr</string>
            <string>UNIX-CONNECT:/Users/YOUR_USER/Library/Containers/com.maxgoedjen.Secretive.SecretAgent/Data/socket.ssh</string>
        </array>
        <key>RunAtLoad</key>
        <true/>
        <key>KeepAlive</key>
        <true/>
    </dict>
    </plist>
    

    Load it:

    launchctl load ~/Library/LaunchAgents/com.user.ssh-agent-relay.plist
    

    Security Considerations

    Both methods rely on Tailscale’s encrypted network, but:

    • SSH forwarding adds another layer of encryption and authentication
    • socat exposes the port to your entire Tailscale network—anyone on your tailnet with access to that port can use your keys

    For most personal setups, either is fine. For shared tailnets, prefer SSH forwarding or add Tailscale ACLs to restrict access to the port.

    Quick Reference

    MethodCommand (from remote server)
    SSHssh -L /tmp/agent.sock:/path/to/agent.socket user@mac
    socatsocat UNIX-LISTEN:/tmp/agent.sock,fork TCP:mac-ip:22122

    Then: export SSH_AUTH_SOCK=/tmp/agent.sock

  • 减脂增肌计划 – 20250324

    减脂增肌计划 – 20250324

    个人情况总结

    • 基本数据:…
    • 体脂状况:…
    • 训练经验:近期有HIIT训练经验,但无系统训练经历
    • 健康状况:膝盖不佳,后背和颈部偶有酸痛,目前腰部有疼痛
    • 可用设备:哑铃和瑜伽垫(家庭训练)
    • 时间安排:每天最多1小时训练时间
    • 饮食习惯:三餐规律,已开始控制碳水摄入
    • 首要目标:减脂为主,兼顾健康肌肉发展,追求健康体魄

    训练计划

    每周安排

    星期训练类型时间强度
    周一力量训练A(上肢与核心)30-40分钟中等
    周二低强度有氧40分钟最大心率60-70%(约109-127次/分钟)
    周三力量训练B(下肢与核心)30-40分钟中等
    周四完全休息/轻度拉伸15-20分钟
    周五力量训练C(全身轻量)30-40分钟中等
    周六低强度有氧40分钟最大心率60-70%(约109-127次/分钟)
    周日灵活安排(休息或轻度活动)视情况而定

    详细训练动作

    A日 – 上肢与核心训练

    1. 哑铃俯卧撑变式
    1. 哑铃单臂划船
    1. 哑铃肩推
    1. 修正式俯卧撑(可从膝盖式开始)
    1. 平板支撑

    B日 – 下肢与核心训练(膝盖友好版本)

    1. 哑铃箱式深蹲(控制深度保护膝盖)
    1. 哑铃箭步蹲(轻重量)
    1. 臀桥(强化臀部,减轻膝盖压力)
    1. 侧向平板支撑
    1. 猫牛式(缓解背部疼痛)

    C日 – 全身轻量训练

    1. 哑铃硬拉(轻重量,注意腰部保护)
    1. 哑铃推举
    1. 哑铃弯举
    1. 超人式(强化后背)
    1. 轻度瑜伽拉伸

    有氧训练指南

    • 步行方案:40分钟步行,保持心率在109-127次/分钟
    • 可使用心率监测设备或手动测量(15秒内脉搏次数×4)
    • 视频指导:Keep健走课程
    • 居家低冲击有氧:适合天气不佳时
    • 视频教程:Fitness Blender低冲击有氧

    饮食计划

    热量与营养目标

    • 热量:每天摄入约2000-2200卡路里(适度热量赤字)
    • 蛋白质:每天180-200克(约占总热量的35-40%)
    • 碳水化合物:每天150-180克(约占总热量的30-35%)
    • 脂肪:每天55-65克(约占总热量的25-30%)

    每日饮食安排

    早餐(约600卡路里)

    • 2个全蛋(炒、煮或水波蛋均可)
    • 30克蛋白粉(混入麦片或单独冲饮)
    • 30-40克全谷物麦片或燕麦片
    • 100克新鲜水果(如蓝莓、苹果、香蕉)
    • 240毫升低脂牛奶或无糖植物奶

    午餐(约700卡路里)

    • 250克瘦肉蛋白质来源(鸡胸肉、瘦牛肉、鱼肉或豆腐)
    • 50克煮熟的糙米、藜麦或红薯
    • 200克非淀粉类蔬菜(西兰花、菠菜、青椒等)
    • 10毫升橄榄油或亚麻籽油(烹饪用)

    晚餐(约600卡路里)

    • 200克蛋白质来源(与午餐不同类型,保持多样性)
    • 无主食(保持当前无主食习惯)
    • 250-300克各色蔬菜(中式炒菜)
    • 15克健康脂肪来源(坚果、橄榄油、牛油果等)

    加餐选项(约200卡路里,根据饥饿感选择)

    • 1份希腊酸奶(170克)+ 5-10克坚果
    • 1个水煮蛋 + 1个小苹果
    • 蛋白棒(确保低糖,高蛋白)
    • 25克蛋白粉 + 水或牛奶冲调

    蛋白粉推荐

    推荐蛋白粉类型:乳清蛋白隔离粉(Whey Protein Isolate)

    推荐品牌

    1. Optimum Nutrition Gold Standard (国际知名品牌)
    2. MyProtein Impact Whey Isolate (性价比高)
    3. 纯沛(中国本土品牌,品质可靠)

    使用建议

    • 早餐与麦片一起食用或训练后30分钟内食用
    • 每次25-30克(约一勺)
    • 可与水、牛奶或植物奶混合

    进展监测与调整

    每周监测指标

    • 体重(每周一早晨空腹测量)
    • 能量水平(主观评分1-10)
    • 训练表现(记录重量或完成次数)
    • 睡眠质量(主观评分1-10)

    每月监测指标

    • 腰围(每月1日测量)
    • 关节健康评估(特别是膝盖和背部)
    • 照片记录(同一角度、光线和时间)

    调整原则

    1. 体重每周下降0.5-1公斤为理想,若过快或停滞则调整热量摄入
    2. 如关节不适,立即减轻训练强度或改变动作
    3. 每4周评估整体计划,根据进展调整训练和饮食

    特别注意事项

    1. 充分水分摄入:每天至少2.5升水
    2. 睡眠保障:每晚尝试保持7-8小时睡眠
    3. 循序渐进:前两周以适应训练为主,逐步增加重量和强度
    4. 灵活调整:根据身体反馈随时调整训练计划,膝盖和背部不适时及时休息
    5. 保持记录:简单记录训练和主要饮食,帮助追踪进展

    12周目标

    • 体重减至85kg左右(平均每周减重约0.67kg)
    • 腰围减至95cm以下
    • 建立基础力量,完成15个标准俯卧撑
    • 改善整体体能,减轻关节不适感
  • I ate some delicious dumplings today

    I ate some delicious dumplings today

    Asian food, dumplings

    What did you eat for dinner today?