This version (2017/05/27 13:44) is a draft.
Approvals: 0/1

[10:42:14] <cescoffier> hi davsclaus

[10:42:16] <davsclaus> cescoffier okay got some code

[10:42:32] <davsclaus> will do a PR shortly with 50% done

[10:42:46] <cescoffier> cool, what are you improving ?

[10:43:03] <davsclaus>

[10:43:12] <davsclaus> to leverage camel's routing engine correctly

[10:43:21] <davsclaus> same kind of work needed in the outbound

[10:43:26] <davsclaus> will take a look in a while

[10:44:41] <cescoffier> so you use AsyncProcessor

[10:44:51] <cescoffier> in which thread is this processor called ?

[10:45:20] <davsclaus> the camel consumer

[10:45:23] <cescoffier> (same question for callback.done())

[10:45:32] <cescoffier> so a thread pool managed by camel

[10:45:33] <davsclaus> but the reply part is the vertx thread

[10:45:55] <davsclaus> so if you do reply then you can “free” the consumer thread

[10:45:59] <davsclaus> when you return false

[10:46:25] <davsclaus> and leave it to vertx to resume the work when it has the reply

[10:46:50] <cescoffier> ok, cool

[10:47:08] <davsclaus> sadly AsyncProcessor is not a single interface so its not java 8 lambda readyu

[10:47:11] <cescoffier> looks much better than my attemp to check in the exchange was InOut

[10:47:42] <davsclaus> i will give a go on the outbound side as well and do a PR there

[10:47:56] <DP_2014> Hi, I have created a web app but as its getting more and more complex with hundreds or routes and handlers It becoming really messy, passing RoutingContext areound every wherem anyone know of a good structure to group and inherit handler functionality?

[10:49:21] <cescoffier> DP_2014 : the handler don't have to be in the same class, you can create one class per handler if you want

[10:50:32] <DP_2014> yes i have done that and grouped handlers in classes like controllers, but when i want base functionalitly and inherit the only way i can get around it is passing REouting context to each method

[10:50:52] <DP_2014> sorry passing RoutingContext

[10:52:05] <DP_2014> this is all pretty much just like controllers no other services I ahve about 20 other verticles that handle all the services, I am having trouble with the complexity of the routing

[10:55:36] <DP_2014> has anyone used routing with hundreds of routes?

[10:59:14] <cescoffier> ping pmlopes

[11:00:13] <cescoffier> pmlopes : DP_2014 has a question for you

[11:01:32] <DP_2014> Lol, I need extension methods like they have in C#

[11:01:56] <pmlopes> @DP_2014 the routing context is a dynamic object it represents the request so you cannot use it as a class variable and set it once on the contructor

[11:02:23] <DP_2014> yes i know, so i have to pass it to every method

[11:02:24] <cescoffier> davsclaus : I've merged your PR, re-eanbled the skipped test (as replies work now), and externalize the helper method into a Helper class.

[11:02:36] <davsclaus> cescoffier nice

[11:03:01] <cescoffier> davsclaus it starts to look pretty good (planning a write a blog post about it)

[11:03:02] <pmlopes> now depending on your objects you could use a generator like approach, you could have a generic class that on its handler method creates a new object of your classes and in that case it will have the routing context in the contructor

[11:03:17] <pmlopes> but this object cannot live longer than the request itself

[11:03:28] <DP_2014> yes thats what i have bee nthinking on

[11:10:26] <DP_2014> pmlopes do you see any downside in that approach?

[11:11:46] <DP_2014> I am also struggling with hundreds of route combination methods, with either a tonne of routes or a switch/case statment in the classes to direct to the correct method? Am i missing something obvious?

[11:12:41] <pmlopes> @DP_2014 if your objects do not do any long initialization, say for example that only set the RC to a object state, then I see them as a extended lambda so performance wise it should be negletable

[11:13:23] <pmlopes> @DP_2014 if you need switch cases to route to the right method, i guess that your API is not as simple as it should be, it shows that you have overlaping

[11:13:34] <pmlopes> maybe you should revisit that too

[11:14:00] <DP_2014> sorry I can either have hundreds of routes , or simple routes and then swtich statements

[11:14:10] <pmlopes> of course i'm saying this without looking at code

[11:14:45] <pmlopes> out of curiosity what kind of system are you building to require hundreds of routes?

[11:16:16] <DP_2014> Its a business system that is being ported for social collaborative scale

[11:17:39] <DP_2014> so full crm, financial accounting, manufacturing , hr, inventory, etc but on a collaborative model

[11:18:08] <pmlopes> so if you have simple routes and switch statement how would that look like?

[11:18:38] <DP_2014> it has been ported from c#

[11:18:49] <DP_2014> taken about a year to port

[11:19:35] <DP_2014> “area1/action1 /area1/action2 ../areaN/actionN” [11:20:14] <DP_2014> ite gets more complex than that [11:20:33] <DP_2014> but router.route(“/:vtxarea/:vtxaction”) [11:21:22] <pmlopes> so you could get a simple route with vars like “/:area/:action” and the handler would then create a object that would contain the RC and be suited to handle a specific area+context type [11:21:34] <DP_2014> but its ususally within areas like router.route(“/person/:vtxarea/:vtxaction”).handler(programHandler); [11:21:41] <DP_2014> but its ususally within areas like router.route(“/person/:vtxarea/:vtxaction”).handler(personHandler); [11:23:29] <pmlopes> i guess you can hide the switch statements inside the constructor of your object or use some other smarter technique [11:24:02] <pmlopes> like some hashing given the set of variables give me the object type that can handle it [11:26:23] <DP_2014> or more clearly the url would be something like “/inventory/widget1/stock” would show stock levels for widget1 and “/inventory/widget1/purchasing” would show purchasing for widget1 handler would be inventoryHandler ie. router.route(“/inventory/:vtxid/:vtxaction”).handler(inventoryHandler); but in the inventory handler i have massive case statment for all the possible… [11:26:24] <DP_2014> …actions [11:26:58] <DP_2014> now multipply this for tens of module areas, [11:29:41] <pmlopes> well, you could try to handle this the other way around, so say you have the route: “/inventory/:vtxid/:vtxaction” you first add a handler that only looks at “vtaction” and sets the right object in the context “ctx.put(“vtAction”, new MyVTActionHandler(ctx, ctx.getParam(“vtaction”))); and then [11:30:04] <pmlopes> now on the following handler you always have the handler type resolved so no need to switch statements [11:30:57] <pmlopes> you just need to do ctx.get(“vtAction”).runMyBusinessLogic(…) and what ever extra needed [11:35:30] <DP_2014> …/stock action will call a method like a stock() that has completely different business logic than …/purchasing purchasing(). also if person puts url /inventory/widget1/badRequest it will still be picked up by the route but is invalid? I do chain the handlers now to session - > auth → data handler →db handler - >render/repsonse handler but in the… [11:35:31] <DP_2014> …middel the data and bus [11:37:57] <pmlopes> you can validate if the action is valid, say having a list of valid actions and do something like: if (!actionsList.contains(ctx.getParam(“vtaction”))) {; } else {; } [11:38:12] <DP_2014> sorry, don't mean to be coming across as being argumentative, your advice has been great, especially the geneerator approach!! I am just trying to get my head around all the issues [11:49:28] <davsclaus> cescoffier a PR with the outbound implemented [11:49:33] <davsclaus> [11:53:23] <cescoffier> thanks davsclaus, gonna have a look after lunch [12:26:02] * ChanServ sets mode: +o temporal_ [13:22:18] <cescoffier> davsclaus : back, having a look [13:36:49] <BadApe> i am using postgresql and the json field type, when i encode the result, the json object field gets converted to a string [13:36:55] <BadApe> is there anyway around this? [13:38:41] <cescoffier> BadApe: are you using the mysql/postgres client or the JDBC async client ? [13:38:48] <BadApe> jdbc client [13:39:27] <BadApe> MySQL / PostgreSQL client says tech preview [13:39:40] <cescoffier> BadApe : I'm not sure we support the Json type. So it is probably passed as a String, and you would need to recereate the Json Object out of it [13:39:57] <cescoffier> BadApe : yes the MySQL / Postgres client is a tech preview [13:40:05] <BadApe> :) [13:40:20] <cescoffier> davsclaus : merged ! Thanks ! I've updated the documentation. So now it's time for the vert.x team review [13:40:24] <BadApe> there is some support :) [13:40:53] <cescoffier> BadApe : didn't read this article, I should ;-). [13:40:56] <davsclaus> you may want to add a bit debug/trace logging on the points where camel and vertx “change hands” [13:41:02] <davsclaus> it may help during some debugging etc [13:42:04] <BadApe> i read all the blog posts, very enlightening for a newbie [13:42:27] <BadApe> they should be changed into a beginners guide [13:42:31] <cescoffier> BadApe : in the snippet, line 88: here we return the document and note that i don't need to convert from JsonObject to String, PostgreSQL returns JSON as strings so less conversions, better performance! [13:43:20] <cescoffier> davsclaus : yes, it would make sense to add a few log, I've done basic thread check to be sure we don't block the event loop [13:43:36] <BadApe> i guess i will have to loop over the results [13:44:21] <BadApe> it doesn't make using the json field type very useful for a rest interface [13:45:06] <cescoffier> BadApe : as far as I understand, it's postgres that returns String objects [13:45:12] <davsclaus> cescoffier +1 [13:46:18] <BadApe> maybe i shouldn't use the json field type [13:56:53] <BadApe> oh it was easier to manually covert it [13:57:01] <BadApe> shame i don't know which are json fields [17:26:51] <BadApe> so i don't really want to write a failure handler for every route, can i do something like [20:38:22] <jtruelove_> temporal_ has there been any thought on allowing AbstractVerticle to have an override like getVertxOptions where you could configure a custom SPI or something for instance [20:38:41] <jtruelove_> i feel like i've asked this before but there was a chicken and egg problem with that [22:41:31] <temporal_> jtruelove_ yes it would be a problem and it would also complexify, a verticle should not own a configuration for vertx [22:41:41] <temporal_> what is the problem you are trying to solve ? [22:52:34] *** ChanServ sets mode: +o temporalfox [23:11:28] <jtruelove_> it would be nice to use say vertx-opentsdb and still use abstractverticle [23:11:42] <jtruelove_> but you need to specify config VertxOptions in order to config the SPI [23:16:12] <jtruelove_> temporal_ ^ [23:27:07] <jtruelove_> err temporalfox ^ [23:27:41] <temporalfox> jtruelove_ btw have you seen my mail about Thomas Segismont work on metrics ? [23:28:48] <temporalfox> jtruelove_ what is your use case exactly ? [23:28:52] <temporalfox> I mean how do you use it ? [23:31:05] <jtruelove_> i saw a mail I have not fully pondered it, it sounded if I'm remembering correctly akin to some things that julien and i discussed a bit back [23:31:30] <temporalfox> I'm julien :-) [23:32:02] <jtruelove_> well then you :) never sure which is the real fox in here [23:32:22] <jtruelove_> well we write most of our services using AbstractVerticle and a fatjar manifest that points at that implementor, doing that doesn't allow you to easily integrate with SPI [23:32:45] <jtruelove_> unless you make a wrapper verticle for injecting our custom vertx-opentsdb options etc.. [23:32:55] <temporalfox> you could make your own verticle factory perhaps [23:33:06] <jtruelove_> so a while back when i did SPI we discussed it and hawkular and some of the similarities [23:33:11] <temporalfox> that setup opentsdb options [23:33:21] <temporalfox> based on the verticle class or annotations [23:33:58] <temporalfox> actually : chicken egg problem [23:34:24] <jtruelove_> yeah, you have to start the verticle with the vertxoptions [23:34:38] <jtruelove_> it's how the SPI shit gets injected ultimately right [23:34:41] <temporalfox> I think the best if you use a fat jar is to make your own Launcher [23:34:48] <temporalfox> and extend the exisint CLI launcher [23:34:58] <jtruelove_> yeah which will take the insatnces args and things and pass them in [23:35:11] <jtruelove_> and just start the verticle [23:35:11] <temporalfox> it will prepopulation the options [23:35:13] <temporalfox> yes [23:35:38] <jtruelove_> it would just be nice if you could have SPI options returned but i get why you can't [23:36:04] <jtruelove_> on the thomas thing, i think you guys are discussing a common interface for reporting gauges, counters, and timers via the event bus [23:36:07] <jtruelove_> and also maybe directly [23:36:16] <temporalfox> we are discussing two things [23:36:19] <jtruelove_> which is what vertx-opentsdb does more or less [23:36:19] <temporalfox> 1/ what you said [23:36:41] <temporalfox> 2/ abbstract the hawkular spi implementation to be decoupled from hawkular [23:36:45] <temporalfox> and have hawkular only being a reporter [23:37:11] <temporalfox> so the generic SPI impl gather statistics and periodically flush them in hawkular using a rest client [23:37:20] <temporalfox> because these days many TSDB work this way [23:37:30] <temporalfox> hawkular, opentsdb, influxdb, etc… [23:37:35] <jtruelove_> yeah exactly [23:37:42] <temporalfox> that would allow to have in common this collecting spi code [23:37:43] <jtruelove_> some don't support gauges but other than that [23:37:56] <jtruelove_> and be smart hopefully about batching and things [23:37:59] <temporalfox> I think when you report you get generic statistics [23:38:11] <temporalfox> and then it's up to the reporter to take care of this :- [23:38:13] <temporalfox> :-) [23:38:37] <temporalfox> I think thomas wants also to make a persistent queue [23:38:47] <temporalfox> so if metric server is down [23:38:51] <temporalfox> metrics are stored there [23:38:54] <temporalfox> and queued [23:38:57] <temporalfox> until it comes back [23:39:36] <jtruelove_> interesting, could be good but could also be a pain in the ass [23:39:52] <temporalfox> I think this would be optional [23:39:52] <jtruelove_> depending on how long it would take data before purging [23:40:11] <temporalfox> but you can discuss that on vertx-dev if you are concerned [23:40:19] <jtruelove_> or popping longest in the queue data etc.. [23:44:27] <jtruelove_> i'll try and engage on that thread