Open curran opened 7 years ago
FWIW, I'm using sharedb-mongo, and I see that those values are stored in the database. A whole document looks something like this:
{
"_id" : "1569dee41c42424cb0c5800e621020b6",
"title" : "A new thing",
"description" : "Testing",
"_type" : "http://sharejs.org/types/JSONv0",
"_v" : 3,
"_m" : {
"ctime" : 1499677902674,
"mtime" : 1499678012715
},
"_o" : ObjectId("5963453c78cc1e784f6cb1ad")
}
Proposal for ShareDB API change: expose mtime
and ctime
to client-side documents.
User story:
As a developer using ShareDB,
I would like to be able to access the modified and updated times for a document,
so that I can present that information to end users.
@curran Hi, curran, could you tell me how do you add "title" and "description" when create the doc? thx.
@domonless I'm using the ShareDB API to create the document and add those fields, like this:
import connection from '../connection'
import { DB_DOCUMENTS_COLLECTION } from '../../constants'
import generateId from '../generateId'
// Creates a new document in the ShareDB backend,
export const createDocument = options => {
const {
title,
description
} = options
const id = generateId()
const doc = connection.get(DB_DOCUMENTS_COLLECTION, id)
doc.create({
// Human readable title, String.
title,
// Human readable description, String.
description
})
return doc
}
I'm still interested in accessing ctime
and mtime
. Would a PR be welcome that exposes these?
@curran Thank you, I will try this and I think accessing ctime and mtime will help a lot. I am currently use some side function log then send these meta info, it is not a pleasant experience.
Any update on this issue? I'm also trying to access the m.mtime in the client. In my case, I'm creating a SubscribeQuery to a projection to show the list of documents. I'd like to show the modification time in the list. I tried passing options.metadata=true when I created the SubscribeQuery, but it seems even though the mongo driver receives that information from the database, it's being filtered out somewhere and the client does no receive this information.
For what it's worth, we use a slightly hacky way of figuring out the creation time from the Mongo ObjectId
: https://docs.mongodb.com/manual/reference/method/ObjectId.getTimestamp/
Doesn't help with mtime
, though unfortunately.
Thanks @alecgibson. Clever hack. Though it's not what I'm looking for, as you mentioned. Since this information is stored in the database by sharedb, and this thread is for 2017, I was hoping this issue is solved by now. So there no way to get the information through the sharedb client itself?
Doing some digging around it looks like you may be able to do something hacky by using a projection with $submit: true
:
https://github.com/share/sharedb/blob/master/test/db.js#L274-L284
So maybe if you did something like this:
backend.addProjection('myCollectionWithMeta', 'myCollection', { $submit: true });
const doc = connection.get('myCollectionWithMeta', 'myDocId');
doc.fetch(() => {
// doc.m should be populated...?
});
Disclaimer: I have absolutely no idea what $submit: true
is actually meant to be used for, so proceed with caution, and maybe do some digging of your own (also I haven't tested that code, so it might even not be right).
Aha, yes, further to my above comment, using $submit: true
should return metadata, because that's what it's intended to do.
That being said, it's been prefixed with a $
, which is usually convention-speak for "this is an internal property and may change in a breaking way at any time," so I'd still proceed with caution if you choose to go this route.
Of course, you could always submit a pull request to add this sort of functionality in a way less hacky way.
Although actually on second thought, it looks like Doc
completely ignores the m
metadata field when ingesting a snapshot: https://github.com/share/sharedb/blob/master/lib/client/doc.js#L158-L204
So actually this probably won't work.
Thanks @alecgibson. Your comments were very helpful. Following your comments, I found out that even though that the $submit:true / metadata:true makes the metadata to be fetched from the database, it will be ignored in the getSnapshotData method in agent.js: https://github.com/share/sharedb/blob/10902b72ae0362471fdc5409f323430a65f4d2b0/lib/agent.js#L416-L425 So the client never receives the meta information. And then as you mentioned, the client implementation itself also ignores this information, even if it was sent.
So, here is what I changed to send the metadata to the client.
---
lib/agent.js | 3 ++-
lib/client/doc.js | 1 +
2 files changed, 3 insertions(+), 1 deletion(-)
diff --git a/lib/agent.js b/lib/agent.js
index 3ef5583..46d6662 100644
--- a/lib/agent.js
+++ b/lib/agent.js
@@ -416,7 +416,8 @@ function getMapData(snapshotMap) {
function getSnapshotData(snapshot) {
var data = {
v: snapshot.v,
- data: snapshot.data
+ data: snapshot.data,
+ m: snapshot.m
};
if (types.defaultType !== types.map[snapshot.type]) {
data.type = snapshot.type;
diff --git a/lib/client/doc.js b/lib/client/doc.js
index 71f4e20..3bc1f80 100644
--- a/lib/client/doc.js
+++ b/lib/client/doc.js
@@ -199,6 +199,7 @@ Doc.prototype.ingestSnapshot = function(snapshot, callback) {
this.data = (this.type && this.type.deserialize) ?
this.type.deserialize(snapshot.data) :
snapshot.data;
+ this.meta = snapshot.m;
this.emit('load');
callback && callback();
};
--
2.18.0
Any concerns?
It all looks generally fine to me. I suspect people will suggest hiding this functionality behind some sort of option/flag, although what exactly that would look like I'm not entirely sure of myself (there are many ways you could do it - set a flag on a Doc
; sending on option on Doc.fetch
; send an option when opening a Connection
, setting an option across all of ShareDB; etc.).
I'd suggest raising a PR and discussing there.
Well, what's missing now is that the update operations received by the client don't have the meta information.
It all looks generally fine to me. I suspect people will suggest hiding this functionality behind some sort of option/flag, although what exactly that would look like I'm not entirely sure of myself (there are many ways you could do it - set a flag on a
Doc
; sending on option onDoc.fetch
; send an option when opening aConnection
, setting an option across all of ShareDB; etc.).I'd suggest raising a PR and discussing there.
Yes that make sense. The meta information is only being sent if the $submit:true
/ metadata:true
is being passed, though. otherwise it won't be returned to the client.
ShareDB adds the creation and last modified date to documents under the
m
(meta) field, asm.ctime
andm.mtime
(in SubmitRequest.prototype._addSnapshotMeta). However, these fields do not appear ondoc
objects after fetching or subscribing. Does anyone know of a way to access these values from within a ShareDB client?