cujojs/meld

Bundle some useful, pre-fab aspect

Closed this issue · 10 comments

Suggested by @scothis. Creating some simple but useful aspects that people can use might help them see the benefits of meld & AOP in general. Also, wire.js could take advantage of them--for example, we could extract the trace aspect from wire/debug, make it available as meld/aspect/trace or somesuch, and wire/debug could use it.

Pre-fab aspect ideas:

  1. method/function tracing: a la wire/debug
  2. simple memoization
  3. more advanced caching? Dev supplies a "cache impl" that implements some simple interface, and aspect uses it to lookup cached values, store new values in the cache, etc. Could probably implement simple memoization with this aspect.
  4. retry: keep trying a function call up to N times until it returns successfully (doesn't throw). Possibly delay between calls (requires returning a promise)? Rethrow after N failures.
  5. promise retry: keep trying a function that returns a promise, until the returned promise fulfills (doesn't reject). Possibly delay between calls? Reject after N failures.

Let's use this issue to discuss ideas, and we can create separate issues for each aspect we decide to implement.

"parameter adapter" aspect: An aspect that uses a dev-supplied function to transform the original arguments before invoking the original function with them. This could be used to do some interesting things, like injecting parameters--e.g. injecting a db connection from a managed pool.

Recently, @treasonx mentioned that he has been using meld to do some interesting things, so it'd be great to get his thoughts here as well.

I like the idea of having some pre-packaged aspects that people could use. I have to be honest I wasnt familiar with AOP before finding meld. But after reading the wikipedia article and reading the API I started to understand.

I would hate to see these aspects built directly into meld. Some of the things I like most about cujo are that the libraries are small, do one thing well, they are performant, and they run anywhere. I would hate to have aspects built in that I would never use. Although the addition may be small. Could this be a plugin or some other build of meld?

Some of my prebuilt aspects:

I personally prefer promise based APIs, so one of the things I did was to add an aspect to wrap the normal node APIs with a promise api. It handles the normal (err, result) callback signature and returns a whenjs promise.

Another aspect I have I like to call Ke$ha. Basically its a tick tock function which just does some simple performance measuring. Normally I set it up so it can add Ke$ha to some of my function calls if the environment is test or dev.

I have a logging aspect which uses winston to log information about function calls.

One of the more complicated aspects I have allocates a postgres connection from a pool and then starts a transaction. If there is an error it rolls back the transaction. It will also return the connection to the pool when complete. This might be hard to make generic since I also have some connection pooling stuff going on here.

Thanks @treasonx!

the libraries are small, do one thing well, they are performant, and they run anywhere

I am totally stealing this line :) Thanks!

I would hate to see these aspects built directly into meld.

How would you feel about them being being housed in the meld repo, but provided as separate modules, e.g. meld/aspect/trace, meld/aspect/profiler, etc.? That way, you'll only need to load the particular aspects you use, and an AMD build would also only include those.

Would that work for you? Or would you prefer an entirely separate repo?

In the meld repo is fine IMO, i dont think hosting them in a separate repo makes sense.

Have you thought of maybe packaging all of cujo as an executable? For example I like how lodash, if you install it properly, will easily allow you to build different variations of the lodash script. For example I do some chrome extension development so I often need a CSP compatible version.. All I have to do is run lodash csp and I get the proper build ready to go.

Maybe the cujo project should have something similar. For example could run something like cujo meld --profiler --trace and it would spit out a nice little bundle for you. This might be applicable for many other combination of cujo scripts for example maybe a promise wrapper aspect cujo meld --when-node-wrapper and there you go. Just a thought.

Agree about keeping everything in the meld repo. That's the strategy we've used for when.js, and it has worked out very well, IMHO.

We've toyed with an executable cujo util, and we have some ideas there. Right now, we're working on cram, which will handle that kind of "bundling", in addition to being able to build and entire app. It might make sense for a cujo executable to be a front end to various things, one of which would be cram. Thanks for the ideas!

The aspects you've created sound great, BTW. Perfect use cases for cross-cutting AOP, IMHO. Are any of them public? I'd love to see how you've used meld :)

My intent when suguesting this to @briancavalier was to provide useful, but barebones, aspects. You could think of these as live 'examples' of how you can use meld and AOP in general.

They certainly don't belong within the meld module, but should be fine within the meld package. meld/aspects/* load just the aspects you want to use.

@treasonx you may be interested in https://github.com/s2js/probes. It's purpose is more advanced performance analysis and sounds simliar to Ke$ha. (I feel dirty writing that sentence...) I'd certainly be interested in your opinion.

@briancavalier I put together a gist of the aspects I am using in a nodejs project. https://gist.github.com/4439383 The project is private so I copied them into this gist (there might be a couple of mistakes). Any feedback would be great!

@scothis probes looks awesome. My ke$ha is just a simple difference of two time stamps.

@treasonx Thanks for sharing those. They're nice and compact, but effective :)

I think we can start simple here, and put together just a couple very simple example aspects that also happen to be minimally useful. Seems like two good candidates are:

  1. a method tracer, and
  2. a simple memoizer

For 1.1.0, those should be good enough. We can add more in 1.1.x, or later, as we think of them.

Calling this done for now, since meld 1.2.0 is just released and has a few bundled with it. We can open separate issues for including new, specific aspects with meld.