javascript - 云功能中的 firebase 分布式计数器扩展

标签 javascript firebase google-cloud-firestore google-cloud-functions firebase-extensions

我正在尝试在云函数中实现 Firebase 的分布式计数器扩展。这个想法是检测何时创建文档,然后在文档中添加一个计数器。下面是我的云函数:

exports.bookmark_increment = functions.firestore.document('questions/{question_id}/bookmarks/{user_uid}')
  .onCreate(async (snap, context) => {

    // compiled client sample code for increment counter
  var sharded = function(t) { var e = {}; function r(n) { if (e[n]) return e[n].exports; var o = e[n] = { i: n, l: !1, exports: {} }; return t[n].call(o.exports, o, o.exports, r), o.l = !0, o.exports } return r.m = t, r.c = e, r.d = function(t, e, n) { r.o(t, e) || Object.defineProperty(t, e, { enumerable: !0, get: n }) }, r.r = function(t) { "undefined" != typeof Symbol && Symbol.toStringTag && Object.defineProperty(t, Symbol.toStringTag, { value: "Module" }), Object.defineProperty(t, "__esModule", { value: !0 }) }, r.t = function(t, e) { if (1 & e && (t = r(t)), 8 & e) return t; if (4 & e && "object" == typeof t && t && t.__esModule) return t; var n = Object.create(null); if (r.r(n), Object.defineProperty(n, "default", { enumerable: !0, value: t }), 2 & e && "string" != typeof t) for (var o in t) r.d(n, o, function(e) { return t[e] }.bind(null, o)); return n }, r.n = function(t) { var e = t && t.__esModule ? function() { return t.default } : function() { return t }; return r.d(e, "a", e), e }, r.o = function(t, e) { return Object.prototype.hasOwnProperty.call(t, e) }, r.p = "", r(r.s = 2) }([function(t, e) { var r = "undefined" != typeof crypto && crypto.getRandomValues && crypto.getRandomValues.bind(crypto) || "undefined" != typeof msCrypto && "function" == typeof window.msCrypto.getRandomValues && msCrypto.getRandomValues.bind(msCrypto); if (r) { var n = new Uint8Array(16); t.exports = function() { return r(n), n } } else { var o = new Array(16); t.exports = function() { for (var t, e = 0; e < 16; e++)0 == (3 & e) && (t = 4294967296 * Math.random()), o[e] = t >>> ((3 & e) << 3) & 255; return o } } }, function(t, e) { for (var r = [], n = 0; n < 256; ++n)r[n] = (n + 256).toString(16).substr(1); t.exports = function(t, e) { var n = e || 0, o = r; return [o[t[n++]], o[t[n++]], o[t[n++]], o[t[n++]], "-", o[t[n++]], o[t[n++]], "-", o[t[n++]], o[t[n++]], "-", o[t[n++]], o[t[n++]], "-", o[t[n++]], o[t[n++]], o[t[n++]], o[t[n++]], o[t[n++]], o[t[n++]]].join("") } }, function(t, e, r) { "use strict"; var n = this && this.__awaiter || function(t, e, r, n) { return new (r || (r = Promise))(function(o, i) { function s(t) { try { a(n.next(t)) } catch (t) { i(t) } } function u(t) { try { a(n.throw(t)) } catch (t) { i(t) } } function a(t) { t.done ? o(t.value) : new r(function(e) { e(t.value) }).then(s, u) } a((n = n.apply(t, e || [])).next()) }) }, o = this && this.__generator || function(t, e) { var r, n, o, i, s = { label: 0, sent: function() { if (1 & o[0]) throw o[1]; return o[1] }, trys: [], ops: [] }; return i = { next: u(0), throw: u(1), return: u(2) }, "function" == typeof Symbol && (i[Symbol.iterator] = function() { return this }), i; function u(i) { return function(u) { return function(i) { if (r) throw new TypeError("Generator is already executing."); for (; s;)try { if (r = 1, n && (o = 2 & i[0] ? n.return : i[0] ? n.throw || ((o = n.return) && o.call(n), 0) : n.next) && !(o = o.call(n, i[1])).done) return o; switch (n = 0, o && (i = [2 & i[0], o.value]), i[0]) { case 0: case 1: o = i; break; case 4: return s.label++, { value: i[1], done: !1 }; case 5: s.label++, n = i[1], i = [0]; continue; case 7: i = s.ops.pop(), s.trys.pop(); continue; default: if (!(o = (o = s.trys).length > 0 && o[o.length - 1]) && (6 === i[0] || 2 === i[0])) { s = 0; continue } if (3 === i[0] && (!o || i[1] > o[0] && i[1] < o[3])) { s.label = i[1]; break } if (6 === i[0] && s.label < o[1]) { s.label = o[1], o = i; break } if (o && s.label < o[2]) { s.label = o[2], s.ops.push(i); break } o[2] && s.ops.pop(), s.trys.pop(); continue }i = e.call(t, s) } catch (t) { i = [6, t], n = 0 } finally { r = o = 0 } if (5 & i[0]) throw i[1]; return { value: i[0] ? i[1] : void 0, done: !0 } }([i, u]) } } }; Object.defineProperty(e, "__esModule", { value: !0 }); var i = r(3), s = "_counter_shards_", u = "FIRESTORE_COUNTER_SHARD_ID", a = function() { function t(t, e) { this.doc = t, this.field = e, this.db = null, this.shardId = "", this.shards = {}, this.notifyPromise = null, this.db = t.firestore, this.shardId = function(t) { var e = new RegExp("(?:^|; )" + encodeURIComponent(t) + "=([^;]*)").exec(document.cookie); if (e) return e[1]; var r = i.v4(), n = new Date; n.setTime(n.getTime() + 2592e6); var o = "; expires=" + n.toUTCString(); return document.cookie = encodeURIComponent(t) + "=" + r + o + "; path=/", r }(u); var r = t.collection(s); this.shards[t.path] = 0, this.shards[r.doc(this.shardId).path] = 0, this.shards[r.doc("\t" + this.shardId.substr(0, 4)).path] = 0, this.shards[r.doc("\t\t" + this.shardId.substr(0, 3)).path] = 0, this.shards[r.doc("\t\t\t" + this.shardId.substr(0, 2)).path] = 0, this.shards[r.doc("\t\t\t\t" + this.shardId.substr(0, 1)).path] = 0 } return t.prototype.get = function(t) { return n(this, void 0, void 0, function() { var e, r = this; return o(this, function(i) { switch (i.label) { case 0: return e = Object.keys(this.shards).map(function(e) { return n(r, void 0, void 0, function() { return o(this, function(r) { switch (r.label) { case 0: return [4, this.db.doc(e).get(t)]; case 1: return [2, r.sent().get(this.field) || 0] } }) }) }), [4, Promise.all(e)]; case 1: return [2, i.sent().reduce(function(t, e) { return t + e }, 0)] } }) }) }, t.prototype.onSnapshot = function(t) { var e = this; Object.keys(this.shards).forEach(function(r) { e.db.doc(r).onSnapshot(function(r) { e.shards[r.ref.path] = r.get(e.field) || 0, null === e.notifyPromise && (e.notifyPromise = function(t) { return n(this, void 0, void 0, function() { var e = this; return o(this, function(r) { return [2, new Promise(function(r) { return n(e, void 0, void 0, function() { var e = this; return o(this, function(i) { return setTimeout(function() { return n(e, void 0, void 0, function() { var e; return o(this, function(n) { return e = t(), r(e), [2] }) }) }, 0), [2] }) }) })] }) }) }(function() { var r = Object.values(e.shards).reduce(function(t, e) { return t + e }, 0); t({ exists: !0, data: function() { return r } }), e.notifyPromise = null })) }) }) }, t.prototype.incrementBy = function(t) { var e = firebase.firestore.FieldValue.increment(t), r = this.field.split(".").reverse().reduce(function(t, e) { var r; return (r = {})[e] = t, r }, e); return this.doc.collection(s).doc(this.shardId).set(r, { merge: !0 }) }, t.prototype.shard = function() { return this.doc.collection(s).doc(this.shardId) }, t }(); e.Counter = a }, function(t, e, r) { var n = r(4), o = r(5), i = o; i.v1 = n, i.v4 = o, t.exports = i }, function(t, e, r) { var n, o, i = r(0), s = r(1), u = 0, a = 0; t.exports = function(t, e, r) { var c = e && r || 0, f = e || [], d = (t = t || {}).node || n, l = void 0 !== t.clockseq ? t.clockseq : o; if (null == d || null == l) { var h = i(); null == d && (d = n = [1 | h[0], h[1], h[2], h[3], h[4], h[5]]), null == l && (l = o = 16383 & (h[6] << 8 | h[7])) } var p = void 0 !== t.msecs ? t.msecs : (new Date).getTime(), v = void 0 !== t.nsecs ? t.nsecs : a + 1, y = p - u + (v - a) / 1e4; if (y < 0 && void 0 === t.clockseq && (l = l + 1 & 16383), (y < 0 || p > u) && void 0 === t.nsecs && (v = 0), v >= 1e4) throw new Error("uuid.v1(): Can't create more than 10M uuids/sec"); u = p, a = v, o = l; var b = (1e4 * (268435455 & (p += 122192928e5)) + v) % 4294967296; f[c++] = b >>> 24 & 255, f[c++] = b >>> 16 & 255, f[c++] = b >>> 8 & 255, f[c++] = 255 & b; var m = p / 4294967296 * 1e4 & 268435455; f[c++] = m >>> 8 & 255, f[c++] = 255 & m, f[c++] = m >>> 24 & 15 | 16, f[c++] = m >>> 16 & 255, f[c++] = l >>> 8 | 128, f[c++] = 255 & l; for (var g = 0; g < 6; ++g)f[c + g] = d[g]; return e || s(f) } }, function(t, e, r) { var n = r(0), o = r(1); t.exports = function(t, e, r) { var i = e && r || 0; "string" == typeof t && (e = "binary" === t ? new Array(16) : null, t = null); var s = (t = t || {}).random || (t.rng || n)(); if (s[6] = 15 & s[6] | 64, s[8] = 63 & s[8] | 128, e) for (var u = 0; u < 16; ++u)e[i + u] = s[u]; return e || o(s) } }]);
    
    const question_ref = db.collection('questions').doc(context.params.question_id);
    
    // Initialize the sharded counter.
    var bookmarks_count = new sharded.Counter(question_ref, "bookmarks_count");

    bookmarks_count.incrementBy(1);
  });

这个想法是当用户为问题添加书签时。它在相应问题文档内的子集合 bookmarks 中创建一个新文档。然后该函数将检测新文档的创建,并将书签计数器更新 1。我正在尝试使用 firebase 的扩展来执行此操作。但不知何故,当我部署该功能时,计数器不起作用。我在这里做错了什么?

最佳答案

我想指出的是,Firebase Extensions 处于测试版 [1]。 Distributed Counter 文档 [2] 上没有关于 Node.js 的信息;它提到其编译的缩小版 JavaScript [3],并表示用户可以使用提供的客户端示例或您自己的客户端代码来指定您的文档路径和增量值 [4]。

因此,当我们检查 node.js 的分布式计数器文档 [5] 时,用户可以递增并获得 Node.js 上的总计数。

[1] https://firebase.google.com/docs/extensions

[2] https://firebase.google.com/products/extensions/firestore-counter

[3] https://github.com/firebase/extensions/blob/master/firestore-counter/clients/web/dist/sharded-counter.js

[4] https://github.com/firebase/extensions/tree/master/firestore-counter

[5] https://firebase.google.com/docs/firestore/solutions/counters#node.js

关于javascript - 云功能中的 firebase 分布式计数器扩展,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63473176/

相关文章:

angular - Kendo Sortable for Angular - 获取新的索引位置

go - 如何阻止通过 Google Firestore api 访问 Google Firestore

javascript - 替代 Node 中的 fork 过程?

javascript - Firebase.update 失败 : first argument contains undefined in property

javascript - Firebase 公共(public)用户访问限制和防止恶意攻击

Android Firebase 多图上传

java - 如何在单击 Android 中的 Firestore 时删除 ListView 文档?

Javascript base64 编码函数返回未定义

javascript - 如何通过 puppeteer 确定性地使用 CSS 选择器?

javascript - 如何使用多个 OR 动态构建 MongoDB 查询?