【发布时间】:2011-02-24 23:00:43
【问题描述】:
我正在 Google 应用引擎上制作成绩册。我会在每个评分期间跟踪每个学生的成绩。评分周期可以重叠。由于我可能一次显示数百个这样的成绩,我预先计算了服务器上的成绩。因此,对于任何一个学生,我可能有许多计算成绩 - 每个评分周期一个。
现在,教师输入测验的新分数。该分数可能会影响许多计算的成绩,因为它可能属于许多评分期。我需要重新计算所有受影响的成绩。这可能需要很长时间,因为对于每个评分期,我需要获取所有相关分数并对这些分数执行复杂的例程。我认为 30 秒是不够的 - 特别是如果今天数据存储区感觉很慢的话。此外,失败不是一种选择。一些成绩更新而另一些成绩悄然过时是不可接受的。
所以我在想,这是了解任务队列的好时机!
我不是数据库结构或任何方面的专家,但这里是我想要做的事情的概述:
public ReturnCode addNewScore(Float score, Date date, Long studentId)
{
List<CalculatedGrade> existingGrades = getAllRelevantGradesForStudent(studentId, date);
for (CalculatedGrade grade : existingGrades)
{
grade.markDirty(); //leaves a record that this grade is no longer up to date
}
persistenceManager.makePersistentAll(existingGrades);
//DANGER ZONE?
persistenceManager.makePersistent(new IndividualScore(score, date, studentId));
tellTheTaskQueueToStartCalculating();
return OMG_IT_WORKED;
}
这似乎是一种将所有相关等级标记为脏的快速方法。如果中途失败,则返回失败,客户端将知道重试。如果客户端稍后尝试获取脏成绩,我们可以在那里返回错误。
然后,任务队列代码将如下所示:
public void calculateThemGrades()
{
List<CalculatedGrade> dirtyGrades = getAllDirtyGrades();
try
{
for (CalculatedGrade grade : dirtyGrades)
{
List<Score> relevantScores = getAllRelevantScores();
Float cleanGrade = calculateGrade(relevantScores);
grade.setGrade(cleanGrade);
grade.markClean();
persistenceManager.flush();
}
}
catch(Throwable anything)
{
//if there was any problem, like we ran out of time or the datastore is down or whatever, just try again
tellTheTaskQueueToStartCalculating()
}
}
这是我的问题:这是否保证在添加新分数后永远不会有计算成绩被标记为干净?
关注的具体领域:
- 在第一个 sn-p 中,
existingGrades是否总是在新的IndividualScore之前,在危险区域附近? - 是否有可能另一个线程将在危险区域启动任务队列代码,以便在真正输入新的
IndividualScore之前将那些现有的等级再次标记为干净?如果是这样,我如何确保不会发生这种情况(所有年级的交易都已结束)? - 即使下午没有关闭,
persistenceManager.flush()是否足以保存部分完成的计算?
这一定是一种常见的问题。我将不胜感激任何指向教程的链接,尤其是那些 appengine 的链接。感谢您阅读这么多!
【问题讨论】:
-
我有一个做心理测试的产品。用户通过测试输入原始数字,我在构建报告时进行复杂计算循环。尽管有数以千计的方程式与您正在做的类型非常相似,但几乎没有任何滞后,即使同时支持多个用户也是如此。如果只是你使用这个,你可能会有点矫枉过正......
-
感谢您的观点。我预计每次计算需要获取大约 1000 个实体,包括分数和其他一些东西,然后平均放回 10 个实体。可能这可以在单个请求中运行,但我需要一些永远不会使数据处于不一致状态的东西。正是在处理错误时,我开始担心时间不够了——我已经偶尔在其他一些请求中时间不够了。
-
嗯...但是,我想我可以在实际要求成绩时进行更多计算,如果失败返回相同的错误消息,否则我会...
标签: java google-app-engine transactions google-cloud-datastore distributed-transactions