1

我目前正在开发基于播放的(1.2.4)应用程序,用户可以执行某些任务并获得奖励。这些任务需要一些能量,随着时间的推移将会重新填充。基本设置如下:在工作中安排工作!框架

public class User extends Model { 
    public Long energy; 
    public Long maxenergy; 
    public Long cooldown = Long.valueOf(300); 
} 

public class Task extends Controller { 
    public static void perform(Long id) { 
     User user = User.findById(id).first(); 

     // do some complex task here... 

     user.energy--; 
     user.save(); 
     Task.list(); 
    } 
} 

现在我想在冷却时间(5分钟)后重新填充用户的能量。假设用户已经10/10点能量,我想补充一点,已经用了5分钟后,我可以很容易地使用这样的工作:

public class EnergyHealer extends Job { 
    public Long id; 

    public EnergyHealer(Long id) { 
     this.id = id; 
    } 

    public void doJob() throws Exception { 
     User user = User.findById(id); 
     user.energy++; 
     if (user.energy > user.maxenergy) { 
      user.energy = user.maxenergy; 
     } 
     user.save() 
    } 
} 

......并把它在我的控制器权之后的任务已经竞争:

new EnergyHealer(user.id).in(user.cooldown); 

我在这里的问题是,在这种情况下,作业并行调度,因此,如果用户执行2秒后,他执行了先前的任务后的第一个能量点补充任务5分钟,而随后的点仅在2秒钟后重新填充。

因此,我需要将这些工作序列化,例如,假设我有8个10个能量点,那么应该在012分钟内完成,直到所有能量点重新填充。

在相关说明:用户有不同的级别,并获得完成任务的经验,一旦达到某个阈值。他们的水平会提高,并且所有能量点都会被重新填充,不管其中有多少个已经用在上一级中,因此一些工作可能会在执行时被淘汰。

考虑到一千个用户,工作可能并不是完美的选择,所以如果有人对如何实现所描述的场景有想法,我很乐意为您提供帮助!

回答

1

我想你只是把你的工作安排错了。每次他们执行某个动作时,都不应该开始工作,而应该只是有一个外观或者只有在用户不存在的情况下才会开始工作的东西。

  1. 如果作业不存在,创建它,否则什么都不做

  2. 那么这应该加1点能量,

  3. 检查,如果能量是满的,如果是,结束

  4. 如果不是,暂停5分钟

  5. 回到2

+0

韦恩,谢谢你的回答!然而,我担心我不会理解你的解决方案,也许你可以提供一个简短的代码片段:1)外观的外观和你描述的算法是如何被触发的; 2)我在哪里跟踪用户当前的工作,例如,在收到连续的请求后,如何确定是否有作业正在运行(保持有状态的队列或某物)? – alexhanschke

+0

所以不是调用一个工作,而是调用一个可以检查实体上的值的单例对象。此实体将用于确定是否有为您的用户运行的活动作业。根据数据库是否说有工作正在运行,您的单身人员对象可以启动该工作,或不启动。 – Codemwnci

+0

明白了,谢谢! – alexhanschke