-
Notifications
You must be signed in to change notification settings - Fork 25
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
Feedback requested: AsyncConnection and (soon) AsyncManager #10
Conversation
- AsyncConnection uses standard NodeJS callbacks, rather than returning promises or futures or whatever. The reason is: it keeps the interface generic for libraries like PromHx or Tink_Core. It avoids using platform specific things like js.Promise. - I've got an example MysqlJs lib. This probably should belong in a separate lib but during this early stage it is easier to test here. This uses the NPM 'mysql', and has the appropriate '@:jsRequire' metadata. - Next step: see if we can create an AsyncManager...
These will be used in the upcoming AsyncManager.hx Added: macroGetAsync, macroSearchAsync, macroCountAsync, macroDeleteAsync Please note, I also updated the sync versions of the methods to use macro reification as I find it easier to read.
...so we can use a sync Connection where an AsyncConnection is expected
I'm not a nodejs user but I think it's important to keep this in one single library. About question 2 : why not having 3 classes, one for sync IO, one for async IO, one for the common logic ( SQL generation...etc ) Currently the Manager class is really fat ( 740 lines ) so it would become more maintainable if concerns are separated. Its typically a case of "god object" antipattern :) |
We will share logic between the Manager and AsyncManager in BaseManager. This is a first step in refactoring. The unit tests are passing (yay!)
…tion. Because these are implemented by the AsyncConnectionWrapper, we can move forward with deprecating the use of `Manager.quoteList()` and `Manager.quoteAny()` without changing the interface definition of `sys.db.Connection`, which would be a breaking change for the standard lib. Also in this commit: - implement missing function body for `AsyncConnectionWrapper.lastInsertId()` - minor change to the placeholder async tests
Great feedback @bablukid I've started refactoring by creating a separate As I begin to unwind this there is a fair bit of logic that is difficult to re-use in an async context, so lots of refactoring may be required, which makes the PR harder to code review. Hopefully it will make the library more maintainable though! |
I've also realised that |
…class. This allows the synchronous Manager to maintain the existing global static object cache, but an async manager to have a per-instance local cache.
I assume they used to do something productive, but do not anymore. This is not exposed as public API, however it is possible that a subclass exists in someone's codebase that does something in these methods - but it's not documented in any way, so I think getting rid of it is smart. If anyone objects to this change, then perhaps we can revert this commit and document the purpose of the functions so that it is known.
Where possible separate SQL generation methods from methods that actually return the objects.
…thods to Manager - Manager is basically a version of BaseManager that enforces the Connection is always synchronous - As such, it's safe to call the "async" version of the method, and assume a result will be ready immediately - Please note that Manager.getCnx() now returns AsyncConnection not Connection, so I had to change TableCreate to get the connection via Manager.cnx - I think TableCreate will need to be refactored into sync / async versions anyway
Mostly to use `BaseManager.someMethod()` or `manager.getCnx().someMethod()` instead of `Manager.someMethod()`
And clean up some of the resulting errors that were uncovered.
Neko tests are now passing again.
I'm not very happy with the handling of optional arguments in macros, but it will do for now. Any suggestions for a better approach are welcome!
Please note, technically this is a breaking change: for example ufront.db.Object extends sys.db.Object and overrides insert() and update(), whose signatures have now changed. However for the normal use cases, where you extend the class but do not override those functions, the existing usage will still be fully compatible. For example - all the unit tests still pass.
Well, I've done it:
I plan to write async versions of the unit tests and run against a real code base. But other than that it would be good to get some more feedback, and see if people are happy to merge :) |
basically PHP is complaining that BaseManager.nullCompare() was different to Manager.nullCompare(). They were, but in Haxe that doesn't matter for static functions. Apparently it does in PHP? Given that it's private in BaseManager I just changed the name.
The difference is that the Node library expects a field called "password" but other Haxe connections expect a field called "pass"
Currently It's not possible to test on latest haxe versions because #12 has not been merged. |
Thanks for the big work Jason ! Do you think it would be possible to easily migrate synchronous code for neko to nodejs, just by adding Like BTW I heard |
Closing old/stale PRs |
I would like to (finally) work on getting
sys.db.*
to work with NodeJS, which of course means making async versions ofConnection
andManager
(and considering how to handleObject.insert()
etc).Here's what I've done so far:
AsyncConnection
interfaceclass sys.db.MysqlJs implements AsyncConnection {}
using this NPMWhat I want my next steps to be:
Object
to work async.TableCreate.exists()
andTableCreate.create()
.Transaction.run()
andTransaction.isDeadlock()
.MysqlJs
class to a separate repo.But before I go further, I have some decisions to make, and would appreciate feedback:
1. Do we want this in record-macros or as a separate haxelib?
If we want it in a separate haxelib, ignore all further questions and I'll figure it out myself :) But I'd like to merge it in.
2. What approach should I take with the manager?
The existing Manager class has a lot of very old code and covers a lot of edge cases, so I either want to re-use it, or do a clean implementation. My options are:
Adapt Manager to expose both sync and async methods. Actually shouldn't be that hard... these are the only two places we need to update (and then the flow-ons to other functions):
Create a new AsyncManager class, but start from a copy/paste of the old Manager class. Advantage: keep the two separate and a bit cleaner. Disadvantage: code repetition, having to fix bugs in two places etc.
Create a new AsyncManager class from scratch, but make it less magical, so no automatic caching etc. I feel there's two many edge cases here for me to cover appropriately in a first build.
3. Object.update, Object.insert, etc.
Should I bother trying to adapt these functions to be async? One idea would be to define the signature like so:
Where a completion callback is optional, and triggered on both sync and async platforms, but can safely be ignored on sync platforms.
Thoughts? Comments? I'm working on this as a side project for the next week and a bit so would love your thoughts