我们有一个使用 Base64 编码内容将附件传输到后端的应用程序。然后,后端在进行一些操作后将内容移动到存储。这样我们就可以享受世界一流的离线支持和同步,同时最终使用更便宜的存储来存储文件。
最初我们使用updateChildren
一次性设置内容。这种方法效果相当好,但随后用户开始同时上传越来越多的文件,导致最终用户设备中的数据库静默冻结。
然后我们更改代码以使用以下命令一一写入文件FirebaseDatabase.getInstance().getReference("/full/uri").setValue(base64stuff)
,然后使用updateChildren
仅设置元数据。
这允许看似无限量的文件(前提是它被切成最大 9 兆块),但现在我们面临另一个问题。
一旦新内容可用,我们的后端就会使用 Firebase 侦听器开始工作。触发器等待元数据,然后开始处理附件。看来即使客户端设备写入文件before我们设置元数据,后端通常在文件内容可用之前接收元数据。这迫使我们更改后端代码以停止处理并稍后再次检查附件 Base64 数据是否可用。
这可以工作,但并不优雅,并且会浪费 CPU 周期并增加延迟。
我在文档中没有找到任何 Firebase 是否保证后端接收数据的顺序的任何信息。似乎所有内容都是一口气写成的(使用setValue
or updateChildren
) 在后端作为一个原子单元可用。
它是否正确?我可以相信这一点是未来不会改变的事实吗?
我要解决这个问题的方法(如果上面的假设正确)是首先使用updateChildren
在这样的客户端中
"/uri/of/metadata/uid/attachments/attachment_uid1" = "per attachment metadata"
"/uri/of/metadata/uid/attachments/attachment_uid2" = "per attachment metadata"
然后每个base64块使用updateChildren
具有以下有效负载:
"/uri/of/metadata/uid/uploaded_attachments/attachment_uid2" = true
"/uri/of/base64/content/attachment_uid" = "base64content"
我无法对任何数据使用 setValue 来防止意外覆盖,具体取决于写入最终发生的顺序。
这将使我能够听到/uri/of/base64/content
并尝试在每次新附件完成加载时开始处理元数据包。确定所有文件是否已上传所需的唯一操作是获取元数据并查看从 /attachments/ 找到的所有附件 uid 也存在于 /uploaded_attachments/ 中。