最近在做一个即时聊天的APP,其中对DateTime字段精确度要求较高,精确度需要到毫秒级,关系到消息排序及未读消息数量计算的正确性。
在交互时,我们把移动端本地产生消息的毫秒级时间通过API传入Salesforce端,并且用DateTime字段记录下来。结果在排序和未读消息数量计算时,经常发现出现数据计算不正确的问题。
经过仔细排查,发现我们遇到的关于DateTime精准度的第一个问题。我们虽然把毫秒级时间保存在DateTime字段上了,但是毫秒级的时间存入之后,毫秒数就归零了,精准度只到秒。本来以为只是显示的问题,特地测试了下通过getTime()获取毫秒级时间,结果发现DateTime被存入到数据库时,就将毫秒时间抹去,并不像小数位一样存储了实际值。
这个问题倒也不算难解决,添加一个字段就行了,我们添加了个18位的Number类型的字段,用来记录毫秒数,至此,我们实际发出消息的时间终于记录准确了,完美解决了偶尔出现的排序不正确的问题。
但是很快,我们发现第二个问题,未读消息仍然存在计算不正确的情况。问题出在我们用来比较消息是否未读的CreatedDate上,很快我们也加上了另一个Number类型的字段,在before_insert里记录当前时间,用来辅助记录CreatedDate毫秒级数据,将这个Number类型的值替代CreatedDate传输给移动端,这样用户读的最后一条消息的时间时准确的,应该时可以解决未读消息数量的问题了。
然而事情解决了一部分,至少问题出现得并不频繁了,但是有个新的问题,就是在某些情况下,用户传过来读取的最后一条消息的创建时间之后,未读消息数量不能被消灭掉。仔细排查过逻辑,应该是不存在问题的。即使拿CreatedDate和读的最后一条消息准确的创建时间相比,也应该计算正确,毕竟一个CreatedDate是不带毫秒级的创建时间,怎么着也应该比带毫秒的创建时间小,足以消灭掉未读消息数量。那么问题出在哪里呢?
排查数据,我们最后发现这种导致出现问题的数据,毫秒后三位通常是99X,仔细转换时间形式,会发现这个时间其实比CreatedDate分钟数早一分钟,也就是代码执行的时间导致我们在before_insert里捕获到的时间,会比实际将数据插入salesforce的时间早几个毫秒,所以在跨秒的时候,就会出现这种问题。发现了问题的根源,这个问题就比较好解决了,我们在未读消息数量的计算上,索性也把比较字段换成了number字段,更加精准无误地计算未读数量。
至此,我们关于DateTime精准度导致的问题终于都解决了,也算皆大欢喜了,不过对于Salesforce存储DateTime字段不保留毫秒这个操作还是挺费解的。