Approvals: 0/1
[01:49:35] * ChanServ sets mode: +o purplefox [02:50:07] * ChanServ sets mode: +o purplefox
[09:28:20] * ChanServ sets mode: +o purplefox
[09:40:57] <temporalfox> jtruelove hi
[09:41:17] <temporalfox> pmlopes hi I have a couple of questions for you
[09:41:34] <pmlopes> hi
[09:42:45] <temporalfox> in vertx.x web or redis/jdbc do we have use case with List/Set containing null ?
[09:43:40] <pmlopes> as argument or as reply?
[09:43:54] <temporalfox> both
[09:43:54] <pmlopes> or it doesn't matter?
[09:44:08] <temporalfox> I'm figuring out the current javascript support for nullable
[09:44:38] <temporalfox> and the reality of the current apis
[09:44:44] <temporalfox> if we really need/use this feature
[09:45:00] <temporalfox> I believe it makes sense for data stuff that can have null return or null insert
[09:45:37] <temporalfox> as you worked a bit on database stuff (redis / jdbc) I wnated to check with your the use cases
[09:45:40] <pmlopes> i am looking at redis code and a list might contain null values since it is a perfect valid for redis
[09:45:53] <temporalfox> if we need it and then we need to properly support it in the codegen TCK
[09:45:54] <pmlopes> i even need to encode them in a special way
[09:46:13] <temporalfox> ok
[09:46:21] <temporalfox> so that would be an argument
[09:46:33] <pmlopes> oh and i know that we also need it for the jdbc client
[09:46:46] <temporalfox> what type is it ?
[09:46:55] <temporalfox> List<String> ?
[09:47:21] <pmlopes> oh no, for jdbc it is a json array
[09:47:34] <temporalfox> json is different
[09:47:43] <pmlopes> when you have query placeholders ? they can be null
[09:47:57] <temporalfox> so what do we have for List/Set/Map ?
[09:48:43] <pmlopes> humm in that case we could deprecate the redis API and propose a new one using JsonArray
[09:49:17] <temporalfox> jdbc seems to use JsonArray
[09:49:20] <pmlopes> for a quick find and count it seems that we would need to deprecate 34 method :|
[09:49:20] <temporalfox> in SQLConnection
[09:49:40] <temporalfox> pmlopes what do you mean ?
[09:49:56] <pmlopes> no, sorry in redis, in redis
[09:50:40] <pmlopes> in redis there are 34 methods that take List<String> and they can have both null or not null values, however i think we could propose a API update to replace that with JsonArray
[09:51:02] <temporalfox> like
[09:51:03] <temporalfox> RedisClient evalsha(String sha1, List<String> keys, List<String> values, Handler<AsyncResult<JsonArray» handler);
[09:51:10] <pmlopes> yes
[09:51:12] <temporalfox> I think it's fine to have nullable
[09:51:28] <temporalfox> if it's string I think List<String> is better
[09:51:32] <temporalfox> and we should keep it
[09:51:44] <temporalfox> my point isthat I'm not sure JavaScripr properly supports null in lists
[09:52:01] <pmlopes> ['a', null] is perfectly valid
[09:52:27] <temporalfox> ok
[09:52:41] <temporalfox> I think we miss at least TCK use cases
[09:52:50] <temporalfox> for testing such behavior cross languages
[09:53:06] <pmlopes> even more weird stuff like ['a', null, undefined] is allowed ;) don't you love it now :)
[09:53:27] <temporalfox> but that would not make sense for vertx
[09:53:40] <temporalfox> and that would result in some kind of errors thrown by vertx-lang-js
[09:53:45] <temporalfox> wouldn't it ,
[09:54:40] <pmlopes> it depends if someone is checking for nulls with == then null or undefined are considered null, however if one checks with === then only null is null
[09:55:07] <temporalfox> that's why we need a TCK
[09:55:08] <pmlopes> the bad side is that if one uses == then 0, '', false are also null :)
[09:55:17] <temporalfox> at the moemnt we use typeof on arguments
[09:55:29] <temporalfox> and I know that type null is “object”
[09:55:32] <temporalfox> in JS
[09:55:39] <temporalfox> and the shim is ok with that
[09:55:45] <temporalfox> then there is a null check in the conversion
[09:55:55] <temporalfox> that means today we don't accept null functions
[09:56:10] <temporalfox> for instance vertx.close(null) is acceptable by Vert.x core
[09:56:20] <temporalfox> in JS vertx.close(null) throws a TypeError
[09:56:21] <pmlopes> where can i add javascript TCK tests?
[09:56:33] <temporalfox> that would rather be custom JS cases I think
[09:56:36] <temporalfox> as they would contain null
[09:56:45] <temporalfox> like you do a Vert.x API in JS
[09:56:49] <temporalfox> codegen
[09:56:55] <temporalfox> like
[09:57:02] <temporalfox> checkList(List<String>)
[09:57:06] <temporalfox> and you call it with undfined
[09:57:10] <temporalfox> and see what happens
[09:57:15] <temporalfox> (tdd style)
[09:57:29] <temporalfox> TCK would be more for Nullable collections
[09:58:21] <pmlopes> the best way to test for null in js would be (if value === null || value === undefined)
[09:58:46] <pmlopes> then we have a behavior like java for instance
[10:00:49] <temporalfox> ah you mean that undefined would be considered as null ?
[10:01:20] <pmlopes> yes
[10:02:03] <pmlopes> and i think that for most use cases in js that is fine specially it what matters to call vert.x code
[10:04:49] <temporalfox> yes we should rather be permissive if we pass undefined explictely
[10:05:01] <temporalfox> as long as it does not have impacts on overloading
[10:07:01] <pmlopes> how do you run the TCK?
[10:08:51] * ChanServ sets mode: +o purplefox
[10:09:37] <temporalfox> mvn clean test
[10:09:42] <temporalfox> TCK is ApiTest
[10:09:49] <temporalfox> then you have extra tests around
[10:09:53] <temporalfox> to test special cases in JS
[10:09:58] <temporalfox> and that what you would do
[10:10:13] <temporalfox> but before working on that we should first agree on the global nullable behavior
[10:10:24] <temporalfox> cf my point about nullable function/handler
[10:12:58] <pmlopes> currently in core handlers are not optional, they do not take nulls so we can do the same for JS if handler === null or handler ===undefied then it is a type error i think
[10:14:08] <pmlopes> the undefined is important for cases like: redis.get('key') since i did not pass a second arg js will interpret the second arg as undefined
[10:22:33] <purplefox> pmlopes: temporalfox cescoffier: morning guys
[10:22:42] <temporalfox> hi
[10:22:43] <pmlopes> good morning
[10:22:43] <cescoffier> morning
[10:23:00] <temporalfox> pmlopes null handler has impact on overloading check
[10:23:22] <temporalfox> pmlopes and yes some handlers are optional
[10:23:28] <temporalfox> for instance : vertx.close(null) is valid
[10:23:42] <temporalfox> if you look at Pump implemnetation
[10:23:48] <temporalfox> it calles an handler with null value
[10:27:01] <pmlopes> can you share an example where you're having trouble with js maybe it would be easier for me to fully understand the problem
[10:27:02] <cescoffier> purplefox, pmlopes, temporalfox : if you all agree with the tags proposal, I will update the wiki
[10:27:18] <pmlopes> @cescoffier +1 for the tags
[10:27:26] <temporalfox> pmlopes I sent an example on vertx-dev in reply to myself
[10:27:37] <pmlopes> ok
[11:44:31] <purplefox> temporalfox: hi julien
[11:44:41] <purplefox> temporalfox: quick question on EventBusMetrics:
[11:44:45] <purplefox> void messageSent(String address, boolean publish, boolean local, boolean remote);
[11:45:05] <purplefox> can “local” and “remote” ever be the same?
[11:45:15] <purplefox> if so, why are there two params?
[11:55:07] <temporalfox> purplefox it can be true/true in case of publish that publish both locally and remote on cluster
[11:56:05] <temporalfox> we should update javadoc to be more precise for implementors
[12:01:29] <purplefox> ok, i see thanks
[12:01:57] <cescoffier> pmlopes: did you change the configuration of the vertx-examples build ?
[12:02:24] <pmlopes> i don't think so, why?
[12:02:34] <cescoffier> the build became parameterized
[12:02:40] <cescoffier> by the branch to build
[12:03:12] <cescoffier> well… removing it
[12:03:24] <pmlopes> no i did not do anything on jenkins lately specially about parameterized builds
[12:03:27] <pmlopes> ok
[12:04:26] <cescoffier> the build is failing with “no workspace for vert.x3-examples #640”
[12:10:15] <pmlopes> we also get timeout building web on jenkins it takes more than 30 minutes…
[12:10:18] <cescoffier> ok found the culprit … the github pull request plugin failed
[12:10:27] <cescoffier> 30 minutes !
[12:10:34] <cescoffier> wow, I already increase the timeout
[12:10:40] <cescoffier> 30 min is regally huge
[12:10:47] <pmlopes> yes that is quite stange since it builds in less than 5 on my local machine
[12:10:55] <pmlopes> doing everything including docs
[12:13:13] <pmlopes> there was something wrong with sockjs tests and they blocked for 30 minutes
[12:13:31] <pmlopes> Starting test: SockJSHandlerTest#testNotFound
[12:13:33] <pmlopes> io.vertx.core.VertxException: Connection was closed
[12:13:36] <pmlopes> Thread Thread[vert.x-eventloop-thread-8,5,main] has been blocked for 2990 ms, time limit is 2000
[12:13:38] <pmlopes> Thread Thread[vert.x-eventloop-thread-6,5,main] has been blocked for 2989 ms, time limit is 2000
[12:13:40] <pmlopes> Thread Thread[vert.x-eventloop-thread-8,5,main] has been blocked for 3990 ms, time limit is 2000
[12:13:42] <pmlopes> Thread Thread[vert.x-eventloop-thread-6,5,main] has been blocked for 3990 ms, time limit is 2000
[12:13:44] <pmlopes> Thread Thread[vert.x-eventloop-thread-8,5,main] has been blocked for 4991 ms, time limit is 2000
[12:13:45] <pmlopes> Thread Thread[vert.x-eventloop-thread-6,5,main] has been blocked for 4991 ms, time limit is 2000
[12:13:48] <pmlopes> Thread Thread[vert.x-eventloop-thread-8,5,main] has been blocked for 5990 ms, time limit is 2000
[12:13:50] <pmlopes> io.vertx.core.VertxException: Thread blocked
[12:13:52] <pmlopes> at io.vertx.core.http.impl.ClientConnection.endRequest(ClientConnection.java:339)
[12:13:54] <pmlopes> at io.vertx.core.http.impl.HttpClientRequestImpl.connected(HttpClientRequestImpl.java:552)
[12:13:56] <pmlopes> at io.vertx.core.http.impl.HttpClientRequestImpl.lambda$connect$72(HttpClientRequestImpl.java:515)
[12:13:58] <pmlopes> at io.vertx.core.http.impl.HttpClientRequestImpl$$Lambda$15/1101184763.handle(Unknown Source)
[12:14:00] <pmlopes> at io.vertx.core.http.impl.ConnectionManager$ConnQueue.lambda$getConnection$55(ConnectionManager.java:92)
[12:14:02] <pmlopes> at io.vertx.core.http.impl.ConnectionManager$ConnQueue$$Lambda$128/234250762.handle(Unknown Source)
[12:14:04] <pmlopes> at io.vertx.core.impl.ContextImpl.lambda$wrapTask$3(ContextImpl.java:335)
[12:14:06] <pmlopes> at io.vertx.core.impl.ContextImpl$$Lambda$12/1908698042.run(Unknown Source)
[12:14:08] <pmlopes> at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:358)
[12:14:10] <pmlopes> at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:357)
[12:14:12] <pmlopes> at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:112)
[12:14:14] <pmlopes> at java.lang.Thread.run(Thread.java:745)
[12:14:18] <pmlopes> Thread Thread[vert.x-eventloop-thread-6,5,main] has been blocked for 5990 ms, time limit is 2000
[12:14:20] <pmlopes> io.vertx.core.VertxException: Thread blocked
[12:14:22] <pmlopes> at io.vertx.core.http.impl.HttpClientRequestImpl.handleException(HttpClientRequestImpl.java:326)
[12:14:24] <pmlopes> at io.vertx.core.http.impl.ClientConnection.handleClosed(ClientConnection.java:307)
[12:14:26] <pmlopes> at io.vertx.core.net.impl.VertxHandler$$Lambda$28/1528776789.run(Unknown Source)
[12:14:27] <pmlopes> at io.vertx.core.impl.ContextImpl.lambda$wrapTask$3(ContextImpl.java:333)
[12:14:30] <pmlopes> at io.vertx.core.impl.ContextImpl$$Lambda$12/1908698042.run(Unknown Source)
[12:14:32] <pmlopes> at io.vertx.core.impl.ContextImpl.executeFromIO(ContextImpl.java:225)
[12:14:33] <pmlopes> at io.vertx.core.net.impl.VertxHandler.channelInactive(VertxHandler.java:99)
[12:14:36] <pmlopes> at io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:208)
[12:14:38] <pmlopes> at io.netty.channel.AbstractChannelHandlerContext.fireChannelInactive(AbstractChannelHandlerContext.java:194)
[12:14:40] <pmlopes> at io.netty.handler.codec.ByteToMessageDecoder.channelInactive(ByteToMessageDecoder.java:306)
[12:14:42] <pmlopes> at io.netty.handler.codec.http.HttpClientCodec$Decoder.channelInactive(HttpClientCodec.java:212)
[12:14:44] <pmlopes> at io.netty.channel.CombinedChannelDuplexHandler.channelInactive(CombinedChannelDuplexHandler.java:132)
[12:14:45] <pmlopes> at io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:208)
[12:14:48] <pmlopes> at io.netty.channel.AbstractChannelHandlerContext.fireChannelInactive(AbstractChannelHandlerContext.java:194)
[12:14:49] <pmlopes> at io.netty.channel.DefaultChannelPipeline.fireChannelInactive(DefaultChannelPipeline.java:828)
[12:14:52] <pmlopes> at io.netty.channel.AbstractChannel$AbstractUnsafe$7.run(AbstractChannel.java:621)
[12:14:54] <pmlopes> at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:358)
[12:14:56] <pmlopes> at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:357)
[12:14:57] <pmlopes> at io.netty.util.concurrent.SingleThreadEventExecutor$2.run(SingleThreadEventExecutor.java:112)
[12:15:00] <pmlopes> at java.lang.Thread.run(Thread.java:745)
[12:15:02] <pmlopes> and the it stays there for 30 minutes printing the same exception
[12:17:02] <purplefox> get a stack dump
[12:17:07] <purplefox> it might be a deadlock
[13:06:43] <purplefox> temporalfox: another EventBusMetrics question:
[13:06:44] <purplefox> void handlerUnregistered(H handler);
[13:07:19] <purplefox> What is the argument passed in here? It appears to be untyped
[13:09:52] <temporalfox> the argument is the object returned by handlerRegistered, which is a callback object of the implementation
[13:14:05] <purplefox> why does the metrics need to know that?
[13:31:29] <temporalfox> because it makes the SPI implementation typed and avoid casts
[13:31:59] <temporalfox> for instance
[13:32:00] <temporalfox> https://github.com/vert-x3/vertx-dropwizard-metrics/blob/master/src/main/java/io/vertx/ext/dropwizard/impl/EventBusMetricsImpl.java
[13:32:17] <temporalfox> public void handlerUnregistered(HandlerMetric handler) {
[15:26:48] <melvinross> is there anyway to use npm modules with js vertx in conjunction with maven?
[15:42:19] <melvinross> or just through regular vertx run?
[15:43:32] <pmlopes> @melvinross you can use npm modules with maven at least like this: https://mrhanlon.com/posts/using-npm-bower-and-grunt-with-maven/
[15:43:56] <pmlopes> or if your code is just javascript you can just use npm
[15:45:21] <pmlopes> http://vertx.io/blog/vert-x3-says-hello-to-npm-users/
[15:49:43] <melvinross> yeah, i was just trying to avoid it since it means adding nodejs as a deployment dependency
[15:50:38] <melvinross> i wonder how that maven solution will work with creating fat jars
[15:51:46] <cescoffier> melvinross: what kind of npm modules do you want to use ?
[15:52:16] <cescoffier> melvinross: if you just want to resolve them and embed them in a fat jat, you can use the frontend-maven-plugin
[15:52:35] <cescoffier> melvinross: this plugin installs node locally, and is able to resolve npm modules
[15:52:47] <cescoffier> (it can also call grunt, bower or gulp)
[15:53:05] <melvinross> at the moment, the elastic search module. i may just write an async http client
[15:53:53] <cescoffier> you can do it using the front-maven-plugin then.
[15:54:04] <cescoffier> sorry: frontend-maven-plugin
[15:54:15] <cescoffier> https://github.com/eirslett/frontend-maven-plugin
[15:55:13] <cescoffier> you configure it to retrieve node and npm, and then a second execution to resolve your npm
[15:55:30] <cescoffier> if you place them in the right directory, it should work smoothly
[15:56:06] <melvinross> thanks for the suggestions
[15:56:11] <alvaro_sanchez> purplefox: I will be pushing code for my talk [unknown:ldquo]Vert.x vs Ratpack[unknown:rdquo] in this repo: https://github.com/alvarosanchez/vertx-vs-ratpack
[15:56:28] <alvaro_sanchez> any feedback will be appreciated :)
[16:03:22] <cescoffier> alvaro_sanchez: how are you starting the vert.x app ?
[16:04:15] <alvaro_sanchez> at the moment I just have a hello world. I will create proper gradle-based applications in the following days
[16:08:04] <cescoffier> if you use a fat jar, you don't need the @Grab
[16:12:35] <alvaro_sanchez> yeah I know, I just wanted to have that running directly
[16:13:13] <alvaro_sanchez> making a JAR doesn't prove the point for a hello world (ie: it's an additional step)
[16:15:39] <alvaro_sanchez> I just created that repo, and the hello worlds are just the first step
[16:15:57] <alvaro_sanchez> but my goal is to write a simple REST API in both techs
[16:16:38] <alvaro_sanchez> and they'll be proper gradle-based projects, thus no more Grab's
[16:17:30] <cescoffier> cool
[16:17:35] <cescoffier> will follow ti
[16:18:26] <alvaro_sanchez> thanks!
[16:54:56] <melvinross> cescoffier: thanks for the help. it ended up being a bit of a bust, it can load the module, but fails on relative loads from the module itself, but it was a good exercise [16:55:47] <cescoffier> you embed all the modules in the fat jar ? [16:55:57] <melvinross> yeah
[16:56:29] <melvinross> the files definitely in there. can see it in file-roller [16:57:26] <cescoffier> oh I see, one of the NPM modules is calling 'requires' [16:57:34] <melvinross> yep
[16:57:39] <cescoffier> we may not support this case yet
[16:57:47] <cescoffier> as it's our own 'requires'
[16:59:01] <melvinross__> in case you were wondering, the easiest way i found to get the node modules into the fat jar via shader was to change the workingDirectory to being inside of src/js
[16:59:20] <cescoffier> pmlopes: are you around ?
[16:59:40] <cescoffier> Paulo knows much more things about node, so he may see the issue
[17:04:30] <jtruelove> temporalfox, big takeaways on hawkular?
[17:04:40] <temporalfox> jtruelove hi
[17:04:51] <temporalfox> actually we drawed a path toward inclusion in stack for 3.2
[17:05:04] <temporalfox> and we also discussed possiblity to have a single metrics project
[17:05:14] <temporalfox> containing dropwizard, hawkular in the future
[17:05:20] <jtruelove> interesting
[17:05:23] <temporalfox> and perhaps your work
[17:05:26] <temporalfox> to share things
[17:05:31] <temporalfox> like configuration option
[17:05:53] <jtruelove> yeah i put together vertx-bosun as well which is still pretty immature
[17:05:54] <temporalfox> for instance, in dropwizard it's possible to define which server URI are reported
[17:06:06] <temporalfox> so there is a Match Data Object
[17:06:14] <temporalfox> and hawkular plans to have something similar
[17:06:23] <temporalfox> would make sense to have something common with unified configuration
[17:06:45] <jtruelove> gotcha yeah opentsdb is very generic it's just a time series db that allows for tagging data points
[17:06:47] <temporalfox> in your case, I see hawkular reporting and opentsdb reporting having similar design with timer
[17:06:59] <temporalfox> would be possible to have somethign common
[17:07:11] <temporalfox> and just change the actual reporting
[17:07:20] <jtruelove> yeah i think i'll keep the verticle for listening right now and then everyone publishing to it
[17:07:28] <temporalfox> jtruelove ok
[17:07:42] <jtruelove> otherwise i'd have to elect one instance as 'the' consumer
[17:08:07] <temporalfox> I think in this case the actual reporter could be a straight client (using httpclient for instance)
[17:08:08] <jtruelove> which isn't the worst but it kinda of overloads one thread with all the reporting work + whatever else it's doing
[17:08:10] <temporalfox> or the event bus
[17:08:18] <temporalfox> it would not matter
[17:08:26] <temporalfox> the common stuff would just filter and collect metrics
[17:08:40] <temporalfox> and timely flush this to the actual TSDB
[17:08:51] <temporalfox> (for TSDB I mean hawkular or opentsdb or influx or…)
[17:08:59] <jtruelove> yeah and that works as long as you generically collect
[17:09:04] <temporalfox> there are many these days
[17:09:08] <jtruelove> it's true
[17:09:20] <jtruelove> so that all the info you need is there when it hits the reporter
[17:09:28] <temporalfox> yes
[17:09:40] <temporalfox> I don't think we have time for this in 3.2
[17:09:48] <temporalfox> as thomas needs first to finish his stuff
[17:09:56] <temporalfox> and 3.2 is for end of novebmer
[17:10:15] <temporalfox> but after, I think consolidation is definitely interesting
[17:10:29] <temporalfox> (pretty much like vertx-auth consolidates Shiro, Mongo or Jdbc auth)
[17:25:46] <jtruelove> yeah and i'm more than happy to help out
[17:26:05] <jtruelove> first step is just wrapping up vertx-opentsdb so it can be used by SPI
[17:26:15] <jtruelove> as writing timing metrics in your code is a pain in the ass
[17:59:13] <jtruelove> temporalfox once you get the docs on how to integrate with vertx gen i can incorporate that stuff as right now i see the annotations but don't know where to start
[18:01:03] <jtruelove> have you seen the stuff we are doing with exovert at all? https://github.com/cyngn/exovert
[18:06:52] <temporalfox> jtruelove what do you expect from these docs exactly ?
[18:15:36] <jtruelove> just a walk through / tutorial on how to use and support the code generation features
[18:47:17] <temporalfox> so you mean for writing a polyglot API ?
[18:47:24] <temporalfox> jtruelove so you mean for writing a polyglot API ?
[18:48:21] <jtruelove> yeah more less
[18:48:27] <jtruelove> err or less
[18:48:49] <temporalfox> what is your goal ?
[18:48:56] <jtruelove> although as long as your library uses the event bus you can sorta get that anyway
[18:48:56] <temporalfox> I mean what would you do better with that ?
[18:49:19] <jtruelove> i guess if you want your library usable from any of the vertx languages you'd need that right?
[18:49:35] <temporalfox> what it buys is to have a polyglot API
[18:49:40] <temporalfox> so you have typed client
[18:49:48] <temporalfox> it can also use event bus with service proxies
[18:50:22] <temporalfox> so you have polyglot service proxies that invoke via event bus the underlying service
[18:50:50] <jtruelove> yeah that is what i was alluding to more or less with the event bus comment above
[18:50:59] <temporalfox> ok
[18:50:59] <temporalfox> the current guide talks more about the concept of codegen which are targetted from shim implementors
[18:51:06] <temporalfox> but it should / could be read by api designers
[18:51:17] <temporalfox> there should be a complementary guide for api authoring
[18:51:26] <temporalfox> that explains the setup
[18:51:36] <jtruelove> like so you want a niced typed metric publisher for any lang even though you deploy the consumer in java etc..
[18:52:01] <jtruelove> how you would get that is with the gen stuff it seems
[18:52:21] <jtruelove> granted they could look at the docs and see oh i can write my own i send to this topic with this message structure
[18:52:28] <jtruelove> it just lowers the barriers to use etc..
[21:13:10] *** ChanServ sets mode: +o purplefox