-
Notifications
You must be signed in to change notification settings - Fork 456
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Rewrite JSON API #230
Rewrite JSON API #230
Conversation
tedsuo
commented
Jul 12, 2013
- JSON Client passes tests, but surely has whatever previous bugs or quirks
- json.html in prototype server runs the code currently at https://github.com/share/ShareJS/wiki/JSON-Client-API
ot-types has been renamed to simply 'ottypes' - hence travis build failed. |
Also, lets fix the old bugs while we're at it. The problem is that if you do doc.at(path1), then move path1 to path2, the subdoc object doesn't move. |
ok, I'll add a test for that and resubmit. |
* created example at prototype/public/json.html * tests pass, except for event emitting * make includes json client
using new lifecycle: _beforeOp,submitOp,_onOp
operation changes their position
@nornagon can you comment on this? Does this fix the problems you were having? I'm inclined to accept it. |
@@ -0,0 +1,425 @@ | |||
// Generated by CoffeeScript 1.6.2 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this actually just the compiled output from the old code, or have you changed it? If the former, its still buggy. If the latter, please remove this comment. (In general, we should clean it up so it doesn't look like generated code)
Ok, I believe I fixed the list move issue.
I also ported the sortable train list example to your prototype server. It appears to work, except the server does not seem to be saving the move operations for some reason. |
|
Right now _onOp is only triggered for remote operations. But I need capture the local operations as well. Perhaps that's a bug? |
It should be triggered by any operation that comes from a different context. The operations that are applied locally by the JSON API itself we can probably capture directly... |
We had discussed having ops fire regardless of whether they are local or This would greatly simplify many use cases. When I'm back at the computer
|
@dgreisen we implemented that for regular document op events. The {
_onOp: function(op) { .... },
dance: function() { this.submitOp('dance'); }
} I don't think it makes sense for the local context functions (like dance) to in turn make onOp fire - and it seems lazy to need that. If you really want that behaviour, you could just do this anyway: {
_onOp: function(op) { .... },
_submitAndEmit(op) { this.submitOp(op); this._onOp(op); }
dance: function() { this._submitAndEmit('dance'); }
} |
- observes remote and local moves separately - added destroy method to subdoc
ok, this now works without accessing _doc. btw, once all of this is considered acceptable, I can do a pass to de-cruft the coffeescript generated code. |
Awesome. Uhh - @nornagon ? |
BTW, one thing this change introduces is the need to call destroy on your subdocs, or else you will leak as long as the context is around. On the one hand that's fine, you need to call destroy on your context, and subdoc is basically a context, so it's not weird that you have to destroy it. But the current API makes it not obvious that you're creating state and context that's going to stick around, since it looks like you're just chaining method calls. e.g. this looks like a fine way of using the api, but would cause leaks until context.destroy() is called: context.at('monkey').set({ name:'bobo', banana_hoard:0 }); // can't destroy 'monkey' subdoc!! This pull request is just about getting the json client working again on 0.7, not fiddling with the API, but I wanted to flag that. |
Hm - interesting... I wonder what the best answer for this is. |
... Obviously with weak maps in the next version of javascript we can get around that, but for now...? |
Yeah not sure. I have ideas, but they break the current api and I'd like to actually use Share for a bit before I go around proposing things like that. Given that share is still alpha, maybe it's not a big deal for the moment? One thing I noticed right out of the gate though, I would prefer subdocs to have all the getAt, insertAt methods that the context has. Then I can say: my_monkey = context.at('monkey'); that would get rid of the need for making a lot subdocs, and also make contexts and subdocs the same thing from the users point of view. It feels like subdocs are sort of an implementation detail; as a user I just want a context, and when I grab a node from lower down in the tree, that node is also a context. |
Also, a small breaking change would be to rename 'at' to 'createAt'. Then a least it's obvious that it's a factory method, not an accessor. |
Yep sounds good - and yeah, now's the time to make breaking changes :) (There's heaps of API changes with 0.7 anyway.) |
I think it would make sense to accept this pull after the "coffee cruft" is cleaned up but before making changes to the api. Then we can start changing the api. I like Ted's suggestion to rename There are a couple other changes I'd like to see in the api in order of priority:
I'd appreciate feedback on all three proposals. I'm happy to help with implementation if any of them are oked. |
heyo david,
for at(), how about createContextAt()? Then it matches doc.createContext(). I'd like it to be "create" instead of "get" so that it's clear you're getting a new one: monkey1 = context.createContextAt('monkey');
|
jsonpath; I agree wrt jsonpath in paths. i also can't really think of a use case for it. But it would be nice to have optional dot notation for paths, and jsonpath would be incredibly useful for events. i semiregularly find myself wanting to create a handler for, say, every phone number in a contact. I end up having to create a child op listener and then filtering on paths and ops. but having it built in using jsonpath would be much cleaner.
@josephg; any thoughts? |
One more thing: Events: The way events are handled by the subdoc is, I think, incredibly unintuitive, unless I am completely missing something. iirc, and it's been awhile since I looked into this, to describe a unique json event handler, you must provide an event, a method, and a path. When you call There are many problems with this. a) If i call |
So, the issue is that subdocs now have a destroy() method that must be called to prevent leaks. As soon as you have to destroy(), you're doing manual memory management, and you really want to be able to make independent copies so that different subsystems don't have to coordinate with each other; each can call destroy() when it's done doing it's thing without risk of messing the other guy up. If there's a way to eliminate the need for destroy(), then at() makes sense, you are just accessing the part of the graph at that point. But if subdocs have the requirement that they can update themselves and move about in the graph, they have to observe the context above them for path changes. I don't know of a way to implement this observer pattern that doesn't require cleanup. So as long as we have destroy(), I think it should be createContextAt() or something similar. Regarding events: yeah the issue you are having is share's events are modeled after node's event api, not backbone's. I agree that backbone has a much better system, especially for cleanup. With backbone you can say foo.off(null, null, this) which means "stop listening to whatever I was listening to on foo" which is really great. |
I don't have a strong opinion about this API. I agree that if we're doing manual memory management we should call things create*() and destroy(). I'd like to see the generated coffeescript cleaned up, but I'm leaving it up to you @tedsuo to let me know when you think its ready. I'm not familiar with backbone's events, though that |
Oh hey, I posted the cleanup already, forgot to mention it. |
@josephg: backbone events docs are at http://backbonejs.org/#Events. But it is more useful to read the code: http://backbonejs.org/docs/backbone.html#section-13. An even cooler aspect of backbone events, added in 1.0 is backbone events could easily replace microevents if 3 issues are addressed:
If this is something you would like to see happen, I'd be happy to work on it. |
@tedsuo: I gave thought to subdocs all last night. I think you are correct, there is no way to create a proper subdoc without creating listeners on the doc for moves. So I vote for |
I skimmed your pull, and i think it looks ready to merge once Once this is merged, we can improve the api. |
* optional path and callback arguments everywhere * insertAt(), getAt(), etc merged into insert(), get(), etc * at() changed to createContextAt()
ok, so I made the following changes:
At this point, subdoc is just wrapper methods on the context. They could be the same class, except contexts have to be mixed in to the type.api and so can't use prototypal inheritance. I feel pretty good about it at this point, the API feels clean now. So I'll submit this as final unless there are objections. |
Oh hey one thing Joseph. Uglify rather verbosely complains about how I'm doing polymorphism (checking the arguments array and adding defaults for missing path and callback params). There's no real problem as I can see but I couldn't find a way to tell it to shut up. |
Blah sorry I totally dropped the ball on this. Nice work 💃 Don't worry about uglify - it whinges about heaps of my code too, and as you say there's no way to make it shut up. |
}, | ||
|
||
_onOp: function(op) { | ||
var _results = []; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All this _results, _results1 and the closure is totally unnecessary glup
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
... I cleaned this up a bit after pulling.
Go for it if you like - though a wiki page might work better if you feel you need it. |
Thanks Joseph! Wiki page sounds good to me! Here: https://github.com/share/ShareJS/wiki/0.7-JSON-Client-API |