Saturday, January 02, 2016

fall in love with meteorjs + deploy an app to heroku

yes, fall in love indeed - because for me, a mostly c++ person, the recent developments in web, specifically the rise of javascript as a powerful tool to build apps, went past too quickly to observe and have time to play with. but meteor provides an excellent fundament, a basis, to build javascript/nodejs apps with really not that much frontend knowledge. and i could see this pretty much the first few hours after i started playing with meteor.

why? i had some basic knowledge about javascript, and the knowledge that nodejs is a huge callbacks mess which i don't want to have anything to do with. but here came meteor, and it wraps nodejs so nicely, that i never need to bother about it - and instead with the help of familiar paradigms - RPC, client/server - allows to easily jump and play with things like bootstrap, jquery etc without worrying about servers setup etc

not surprisingly i started with meteor tutorial at http://meteortips.com/first-meteor-tutorial and i must say it is great in laying out the basic principles of building apps with meteor - Spacebars, publications, methods etc. the tempo is well paced and examples quite nice too.

actually i wanted this post to document the steps for deploying the app i built to heroku.com. heroku uses something called buildpacks, to help deploying apps requiring certain development tools in the hosting enviroment. so once you find out that the recommended build pack for meteor is meteor-buildpack-horse the rest is easy, because the github page has detailed info how to deploy. except for one step - if you're using some configuration, provided in a (json) file - e.g. settings.json - in this case the tip provided by geekforbrains at https://gist.github.com/geekforbrains/c8a11d128f13d038b119 is invaluable:
heroku config:add METEOR_SETTINGS="$(cat settings.json)"
mmm...it is good (actually priceless) to have good logging for your app, otherwise it would be quite head-breaking discovering deployment errors - the case "but it works fine on my machine, why doesn't it run on the server? :(", so a simple logging message, 'handling' the situation with the missing settings file, helped me resolve the problem within minutes, instead of, potentially, hours - and that trying to find the error remotely, with potentially multiple deployments and code changes..blah, blah,,,you get the idea

the work on the app is till under progress - it is deployed and available at http://instaplaylist.co. the idea is to drag and drop youtube-hosted videos from various sites and view later on this site (instead of on youtube, which also provides this, and better, and nicer - but hey :)) still under progress - misses a landing page with info etc, but it is fully functional, but lots of ideas to expand it, given time. i'll do my best to post the source to github as well - maybe in a different blog i'll also make a more elaborate post on my experience with the awesome meteorjs

update 18.09.2016: for a new app i had a problem with deploying to  heroku:
- first deploy works fine, logs display meteor 1.2.1
- next day a new deploy - fails, logs display meteor 1.4.1

the solution was to run
heroku config:set BUILDPACK_CLEAR_CACHE=1
(as mentioned here: http://stackoverflow.com/questions/38672782/heroku-rejecting-push-of-a-meteor-app)

Monday, December 14, 2015

javascript drag and drop: problems with dragleave

i don't have much experience with javascript and jquery, but recently i started playing with MeteorJS (and i love it - but about this in a different post).

i'm dragging something onto a div and want an effect of openning jaws. yes, thats right - jaws :) i settled with jquiery-ui toggle, but then decided that addClass/removeClass would be good enough.

and here started the trouble with drag events - as for a single drag over my (large) area i got too many enter/over/leave/exit events, that were causing the "jaws" to toggle non-stop instead of opening on dragenter and closing on dragexit (or dragend - but i never got this event fired; or dragstop - which should be jquiry's killer drag finish event - alas not fired either for some reason).

it took me some time to realize that the nested div and other elements withing the target div were causing this constant enter/leave madness, which was breaking my flow.

so what to do? in an enviroment clean as this one everything is nice and clean, so how can i stop the sub elements from breaking my drag flow? it seems impossible...

so my idea to solve it is based on this:

my events are handled for the div id:
'dragenter #sidebar': function(e, t) {


but what if i'd be able to differentiate between event targets and fire the closing 'close jaw' event when a really non related target sends one of the drag events? but how? here's how:

as you can see, for example on mozilla's site, the drag events have a currentTarget property, but also a relatedTarget property - which it turns out we can use to detect the origin of the previous event - that is, for example - for a dragLeave event: the element that drag operation has left.

so now, our event catcher/handler becomes like this:
  'dragleave .drag-leave': function(e, t) {
    e.stopPropagation();
    e.preventDefault();


aaaaand - we need to add to all subelements of our div the subclass .drag-leave, so that we can check with a simple
if (e.relatedTarget && e.relatedTarget.className.search("drag-leave") == -1) {
      console.log(e.relatedTarget);
      $('#animTarget').removeClass("myClass", 1000, "easeOutSine");
    }



if we should close the jaw and finalize our effect.

so

is this a silly approach? please let me know, for now it works for me

Saturday, October 24, 2015

create a slim and lean docker image for your go/golang application

all well and dandy - we have our app, it is running inside a docker image - yet there is still something we could do better.

hit 'docker images' and take a look at the output

REPOSITORY   TAG        IMAGE ID       CREATED         VIRTUAL SIZE
deligo       latest     11e4c299c1e0   39 minutes ago  755.8 MB
anything bothering you? this 755MB for the image kindda bothered ME.
so much space for an executable, which is less then 1% of this.
lets see how we can improve this

of course, this problem is not something new and many have looked and found solution that satisfies their case. in most cases the solution was using an image of an extremely slim linux distribution - alpine linux

it comes with only about 5 megabytes and through its packaging system - apk - allows you to only install packages you need

now, in my original Dockerfile i was actually building the executable inside the container, but we don't really need this right now, do we? in many cases it would probably make sense - thus the image will be able to grab latest code and build and run the latest executable, but on the other hand you may not wish to have your source code out, even in a secure environment like a docker image.

so, we will just ADD our executable to docker and it will run it away.
here is one of the benefits of compiled go executables - the practically have no dependencies (alright, this is only in my silly case, but i think this is also pointed out by golang dev community as well).

so lets do this.

if we sticked with building our app inside the image we'd have put in the Dockerfile something like

RUN apk add --update go && \
    rm /var/cache/apk/*
but we won't, so we won't: we're are only adding our executable with an ADD command

ADD deligo /go/bin/

and setting the entrypoint

ENTRYPOINT /go/bin/deligo

build and run away!
by the way - here are two useful switches to docker build cmd:
--no-cache=true
--rm
no-cache is especially useful when your executable has changed. i had some problems until realized that docker uses a cache for each step when building the image - which is good, but this cache doesn't seem too smart if it cannot realize a file has changed. so now i use this cmd arg for every build
rm of course removes not needed working data created during the build, and i believe essentially not needed

so, we built the image, we start it with docker run (don't forget to supply -p 8080:8088 or whatever, if your app has IO over ports), and then...
well in my case it was something like
deligo not found
but how it may not be found when i see it in the folder on the image and i can even sh to the image and run the file and..not found!? oh

so while we copied our executable to the image, there still seem to be some dependencies to syslibs which our slim alpine linux doesn't include. we can probably research which and add them, but this will inevitably make our image bigger. may be lets just sigh heavily and do it - include the whole go build chain etc - but turns out this might not even work, because at least for me alpine's
apk --update add go
only added go v1.4, even though i see go v 1.5.1 at their packages site. i found some workarounds for this, but none worked for me.
yet i found an excellent tip on codeship.com 's site, on how to build our go app with all libs statically linked into the executable:
CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o deligo .
further in the article there were some discussions on SSL which i didn't bother to read, instead hurrying to build my app with the tip above and rebuild the docker image, and start it and...yes, it runs!

actually, no - it doesn't :( when my app tries to read/write through the ports, some mysterious message was dumped:
x509: failed to load system roots and no roots provided
what?

nicely, the first search result was this - https://github.com/docker/docker/issues/3825, and mentioning SSL, i remembered the text on codeship's site and so quickly switched to it, to find the final solution: you need to provide certificates to your app, in order to satisfy go’s x509 library
ADD ca-certificates.crt /etc/ssl/certs/ca-certificates.crt
phew
(by the way - is it safe giving out certificates like that, any ideas?)

with this done - the rest is safe sails, and favorable winds...

yes, btw - our docker image got from 750MB to only 15 (15!!!!!) MB!!!
not too bad, eh?