You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现每秒向所有用户发放货币的经济机器人?

实现每秒给所有用户发放货币的经济机器人方案

嘿,你的思路方向完全没问题——用setInterval定时触发+新增未领取收益字段的方式,既能满足每秒发币的需求,还能减少直接修改余额带来的并发风险。下面是我整理的具体实现方案,亲测好用的那种:

核心思路拆解

  1. 给用户数据新增unclaimed字段,专门累计每秒发放的货币(不用每次直接改bal,降低文件写入冲突概率)
  2. 用setInterval每秒触发批量更新逻辑,遍历所有用户累加未领取收益
  3. 封装安全的JSON文件读写工具,处理异步操作和异常情况
  4. 加个简单的锁机制,避免上一次文件操作还没完成就触发下一次,防止数据错乱

具体代码实现

1. 先封装文件读写工具

用Node.js的fs/promises做异步文件操作,比同步操作更适合定时任务场景:

const fs = require('fs').promises;
const path = require('path');

// 固定用户数据文件路径
const USER_DB_PATH = path.join(__dirname, './DB/users.json');

// 读取用户数据的工具函数
async function readUsers() {
  try {
    const data = await fs.readFile(USER_DB_PATH, 'utf8');
    return JSON.parse(data);
  } catch (err) {
    // 如果文件不存在,返回空对象
    if (err.code === 'ENOENT') return {};
    throw err;
  }
}

// 写入用户数据的工具函数
async function writeUsers(users) {
  await fs.writeFile(USER_DB_PATH, JSON.stringify(users, null, 2), 'utf8');
}

2. 实现每秒发币的核心逻辑

这里默认给每个用户每秒发放和workers数量对应的货币(你可以直接改成固定数值,比如1):

// 标记是否正在处理任务,避免并发冲突
let isProcessing = false;

// 每秒发放货币的核心函数
async function distributeCurrency() {
  if (isProcessing) return; // 如果上一次还没处理完,跳过本次触发
  isProcessing = true;

  try {
    const users = await readUsers();

    // 遍历所有用户ID,逐个更新未领取收益
    for (const userId of Object.keys(users)) {
      const user = users[userId];
      // 初始化unclaimed字段(老用户数据里可能没有)
      if (!user.unclaimed) user.unclaimed = 0;
      // 每秒累加货币,这里和workers挂钩,你可以按需调整规则
      user.unclaimed += user.workers || 1;
    }

    await writeUsers(users);
    console.log('本次货币发放完成');
  } catch (err) {
    console.error('发币过程出错:', err);
  } finally {
    isProcessing = false; // 处理完成后解锁,允许下一次触发
  }
}

// 启动定时任务,每秒触发一次
setInterval(distributeCurrency, 1000);

3. 可选:用户领取未结算收益的逻辑

如果需要用户主动领取这些累计的收益,可以加个领取函数:

async function claimUnclaimed(userId) {
  const users = await readUsers();
  if (!users[userId] || users[userId].unclaimed <= 0) {
    return { success: false, message: '没有可领取的收益哦' };
  }

  // 将未领取收益转入余额
  users[userId].bal += users[userId].unclaimed;
  users[userId].unclaimed = 0; // 重置未领取字段
  await writeUsers(users);

  return { success: true, newBalance: users[userId].bal };
}

关键注意事项

  • 并发安全:isProcessing锁是重中之重,因为文件读写是异步的,如果每秒触发太频繁,上一次写入还没完成就开始下一次读取,会直接导致数据覆盖丢失
  • 性能优化:如果未来用户量很大,每秒遍历所有用户可能会有性能瓶颈,到时可以考虑分批处理,或者换成数据库(比如SQLite、MongoDB)代替JSON文件
  • 错误处理:一定要捕获文件操作的异常,避免单个用户的数据错误导致整个定时任务崩溃

内容的提问来源于stack exchange,提问作者Wilk

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 05:57:35