/srv/irclogs.ubuntu.com/2012/04/03/#juju-dev.txt

niemeyermthaddon: ping13:41
mthaddonniemeyer: hi13:41
niemeyermthaddon: Hey man13:41
niemeyermthaddon: We have our first bug to investigate13:41
niemeyermthaddon: For some weird reason the charm at /charm/oneiric/mysql is returning 0 bytes13:42
niemeyermthaddon: Theoretically, this should never happen since the charm is only linked into its final destination at the end of the importing process, which means any errors in between should leave it out13:43
niemeyermthaddon: Oh, wow.. it looks like other charms are empty too13:44
niemeyermthaddon: e.g. oneiric/jenkins13:45
niemeyermthaddon: Can we debug this?13:45
mthaddonniemeyer: sure, can you give me a few mins - have another issue I'm looking at just now13:46
niemeyerSure13:46
mthaddonniemeyer: okay - checking the logs13:50
niemeyermthaddon: There's more than one in that state, so it's not a one-off event13:51
mthaddonniemeyer: nothing interesting in the web app logs - checking charmload13:52
niemeyermthaddon: Please also run this later: db.charms.find({"urls": "cs:oneiric/jenkins"})13:52
niemeyermthaddon: In the juju db13:53
mthaddonniemeyer: https://pastebin.canonical.com/63655/13:53
niemeyermthaddon: Oops.. where's the size?13:55
mthaddonjuju0.453125GB13:55
mthaddonis that what you mean?13:55
niemeyermthaddon: Nope.. I mean I don't see the size in that json output13:56
niemeyermthaddon: Please try this now: db.charms.find({"urls": "cs:oneiric/wordpress"})13:56
mthaddonniemeyer: https://pastebin.canonical.com/63657/13:57
niemeyermthaddon: see the "size" there?13:57
niemeyermthaddon: This is the bug that would happen if the database was loaded with the charmload prior to that update we did13:58
niemeyermthaddon: The reason for dumping the database was avoiding this bug13:58
mthaddonniemeyer: ok, so we need to dump it again, confirm all cronjobs are stopped, and then start again?13:59
niemeyermthaddon: No, now it's too late.. we don't want to break stuff people are using now14:00
niemeyermthaddon: I'll do what I should have done in the first place and write an upgrader14:00
niemeyermthaddon: My laziness clearly didn't pay off14:00
mthaddonokey doke14:00
niemeyermthaddon: okay14:22
niemeyermthaddon: Here is the fix:14:22
niemeyermthaddon: https://pastebin.canonical.com/63660/14:22
mthaddonniemeyer: is there any kind of logging/transactional status to this? just wondering what output you'll want to see to confirm it's done the right thing14:23
niemeyermthaddon: No transactions.. you can exit on the first iteration of the loop if you want to be super sure14:24
niemeyermthaddon: Hold on, will provide it14:24
niemeyerAh, quit, not exit14:27
mthaddonyeah, quit()14:28
niemeyermthaddon: https://pastebin.canonical.com/63664/14:28
niemeyermthaddon: Cool14:28
niemeyermthaddon: This should tell you the first item it fixed, and give you a chance to go look14:28
mthaddonniemeyer: Fixing cs:~4-ja-d/oneiric/appflower14:29
mthaddonniemeyer: how do we verify that, or is that good enough?14:29
niemeyermthaddon: Cool, if you do the find we had above now, with this url, it should show the entry with a size14:29
niemeyermthaddon: Also, in addition to the find, please use .next() at the end14:29
niemeyermthaddon: It will give you better formatted output14:29
niemeyermthaddon: db.charms.find({urls: "cs:~4-ja-d/oneiric/appflower"}).next()14:30
niemeyermore precisely..14:30
mthaddonniemeyer: https://pastebin.canonical.com/63666/14:31
* mthaddon sees size there, suspects that's a good thing14:31
niemeyermthaddon: Yep, looks good.. intact, and has a size which probably matches the actual file14:31
mthaddonok, going ahead with the original paste14:32
niemeyermthaddon: Hold on a second, though..14:32
mthaddonholding14:32
niemeyermthaddon: I'll download the actual charm14:32
mthaddonk14:32
niemeyermthaddon: https://pastebin.canonical.com/63667/14:33
mthaddoncool cool!14:33
mthaddonso go ahead with the first paste?14:34
niemeyermthaddon: Good to go..14:34
mthaddonk14:34
mthaddonniemeyer: and done14:34
niemeyermthaddon: Super, please save the output in case something goes terribly wrong.. unlikely, but whatever14:34
mthaddonniemeyer: https://pastebin.canonical.com/63669/14:34
niemeyermthaddon: Superb, it's in the pastebin for eternity14:35
niemeyermthaddon: Thanks for the help14:35
mthaddonyep :)14:35
mthaddonsure, np14:35
niemeyermthaddon: Btw, do we have access from the charmd process to perform outside queries?14:46
niemeyermthaddon: HTTP queries, more precisely14:46
mthaddonniemeyer: do you mean are the charmd processes exposed directly to the world? no, just through apache -> haproxy14:48
mthaddonapache -> haproxy -> charmd, I mean14:48
niemeyermthaddon: No, I mean the opposite14:48
niemeyermthaddon: Can I query *from* the charmd process into the world14:48
mthaddonniemeyer: all our servers have egress firewalls - if you want to connect to specific things we can make exceptions though14:49
niemeyermthaddon: Cool, it's a specific thing indeed.. I'm pondering about collection of stats14:49
mthaddonk14:49
niemeyerTheMue: ping14:58
TheMueniemeyer: pong14:58
niemeyerTheMue: Heya14:58
niemeyerTheMue: How're things going there?14:58
niemeyerTheMue: How was the presentation?14:58
TheMueniemeyer: has been fine, the audience has been very interested. i only talked too long. ;)14:59
niemeyerTheMue: Nice!14:59
TheMueniemeyer: i have to fix three little typos in the slides and then they will be published14:59
niemeyerTheMue: COol15:00
TheMueniemeyer: but next time i'm keeping the pure talk shorter and concentrate more on a practical part.15:00
niemeyerTheMue: It's easy to go overboard which such a wide topic15:00
TheMueniemeyer: indeed, there is so much you can say about a language like go. and many people didn't know anything about concurrency or higher-order functions15:01
niemeyerTheMue: What was the meeting core topic?  Is it a Linux User Group?15:02
TheMueniemeyer: but i've been asked to talk at other GTUGs (will be called GDG - Google Developer Group - in future)15:02
TheMueniemeyer: a Google User Group15:02
niemeyerTheMue: Hmm.. curious15:03
niemeyerTheMue: A group of users that ... ?15:03
niemeyerUse Google? :-)15:03
TheMueniemeyer: to be more special, a Google technology User Group. android, google apis, dart, go, ...15:03
niemeyerTheMue: Weird.. feels so open15:04
niemeyerAlthough I guess a LUG is equally open15:04
niemeyerTheMue: What about juju land?15:05
TheMueniemeyer: here i'm continuing with real watchers and wait for your lgtm15:06
niemeyerTheMue: Sounds good.. I should dedicate some good amount of time to reviews today15:07
niemeyerTheMue: How's the real watchers stuff going?15:07
TheMueniemeyer: using the watcher package helps, but i had to extend it a bit, you see it in the proposed service config watcher15:08
niemeyerTheMue: Ok15:08
niemeyerTheMue: have you been able to push things forward, or are you blocked?15:08
TheMueniemeyer: if a pipelined goroutine needs to signal an error, it needs a way to tell it to the watcher.15:08
niemeyerTheMue: Isn't that what Stop is for?15:09
TheMueniemeyer: i would say, like roger, that the config watcher is fine. and so i'm continuing based on that (implementing further watches the same way using a new branch based on the config watch branch)15:10
niemeyerTheMue: It doesn't have to be based on if there's no real dependency between them15:11
TheMueniemeyer: Kill() is for signalling errors15:11
niemeyerTheMue: Within the watcher.. something that happens out of the watcher.*Watcher isn't responsibility of that type15:11
TheMueniemeyer: Stop() is the a client/user of a watch can tell that it isn't interested anymore15:12
niemeyerTheMue: Exactly.. and if an error happens outside of that watcher, that's what should be done15:12
niemeyerTheMue: If you're feeling a need to Kill the watcher from outside, some abstraction is being broken somewhere15:13
niemeyerTheMue: I'll be happy to have a look at the branch after lunch15:13
TheMueniemeyer: it's a pipelined goroutine, in case of the config node the data may be invalid (yaml error), but i want to pass this information to the client of the watch. so i Kill() with that error. and the client, calling Stop(), get's this error returned.15:14
niemeyerTheMue: Exactly, that's not right15:14
niemeyerTheMue: You're using the watcher to pass errors for something it has no idea about15:14
niemeyerTheMue: Bad abstraction15:14
niemeyerTheMue: The watcher within the watcher package watches.. it's not supposed to be a conduit for errors of someone else15:15
niemeyerAnyway, really have to step out for lunch.. back in a moment15:15
TheMueniemeyer: the pipelined goroutine needs to tell the watcher 'stop working, there is an error'.15:16
niemeyerTheMue: No, it actually doesn't.. have you ever heard of a function called fkill in C?16:00
niemeyerTheMue: You call it like this: fkill(fd, "My custom error message")16:00
niemeyerTheMue: So that when you do fclose(fd), you can the error back16:00
niemeyerTheMue: Nope.. it doesn't exist, and it's very obviously a weird thing to be doing16:01
niemeyerTheMue: Similarly, it doesn't make sense to be doing watcher.Kill("Completely unrelated error")16:01
TheMueniemeyer: how do you handle it with tomb? tomb.Kill("Ouch") and later err := tomb.Wait()16:03
niemeyerTheMue: The tomb is an internal implementation of the watcher16:05
niemeyerimplementation detail, that is16:05
niemeyerTheMue: There's nothing about the tomb in the watcher's interface.. we can drop it and create the same API without it16:05
TheMueniemeyer: yes, and i'm using this behavior, but only from a pipelined goroutines perspective16:06
niemeyerTheMue: There's no such thing as "pipeline goroutines".. We have a watcher, with an API16:06
niemeyerTheMue: The fact there's a goroutine inside it is irrelevant16:06
niemeyerTheMue: We could have 10 goroutines there, or none16:07
TheMueniemeyer: no, because the goroutine can't directly return an error16:07
niemeyerTheMue: All of that is merely an implementation detail we use to offer the actual API that is documented16:07
niemeyerTheMue: Kill isn't part of the API, and it makes no sense to have it there.. how would we document it?16:07
niemeyerTheMue: // Kill stops the watcher with the given error so that you can call Stop and get the error you provided16:08
niemeyerTheMue: ?16:08
TheMueniemeyer: it is documented, see the prpopose16:08
niemeyerIt's a bad abstraction16:08
TheMueniemeyer: so how would you tell the watcher to end its work and pass the error that led to the error to the user of the watch?16:09
niemeyerTheMue: Again, fkill.. it makes no sense16:09
niemeyerTheMue: The watcher knows about errors in the watch16:09
niemeyerTheMue: It's not supposed to be a conduit for errors happening in logic it has no idea about16:09
TheMueniemeyer: the watcher (the type Watcher) doesn't know about the error16:10
niemeyerTheMue: Exactly, and it shouldn't know about *any* external errors16:10
niemeyert16:10
TheMueniemeyer: the error happens in a goroutine listening to the change16:11
niemeyerTheMue: Exactly16:11
niemeyerTheMue: That's the place to have the error..16:11
TheMueniemeyer: and i have to signal the watcher to stop working16:11
niemeyerTheMue: That's called Stop16:11
TheMueniemeyer: and the Stop() of the service config watcher then has to check if the own stored error is nil and return the value of Watcher.Stop() and otherwise the own error16:13
niemeyerTheMue: It has to do whatever it takes to handle its own problems.. calling foo.PleaseSaveMyError(err) so that foo.HaveYouFailed() when foo is an independent and self-contained abstraction is not nice16:14
TheMueniemeyer: we use tomb as a tool inside the type Watcher, and we use the Watcher inside the special watcher. so why two different kinds of abstraction, why shouldn't care Watcher for its own error management?16:16
niemeyerTheMue: I've been explaining it for a while.. Watcher *is* handling its *own* error management16:17
niemeyerTheMue: What you want is for it to handle somebody else's error management16:17
niemeyerTheMue: and that's not nice16:17
niemeyerTheMue: state/watcher shouldn't be a conduit for somebody else's errors16:18
TheMueniemeyer: tomb is doing the error management of Watcher16:18
niemeyerTheMue: Yes, that's its only purpose in life16:18
niemeyerTheMue: Just like mutexes to mutexing, conditional vars to conditional varing, etc.. those are not exposed either.16:18
TheMueniemeyer: the proposed way Watcher provides a clean API from a users perspective16:19
niemeyerTheMue: It's not a clean API, for the reasons I've been explaining repeatedly16:20
niemeyerTheMue: There's no fkill.. let's not have one in the watcher..16:21
TheMueniemeyer: i'll change it16:22
TheMueniemeyer: but i would like you to do the review first, so i can do the changes at once16:24
niemeyerTheMue: Sure, I'll have a more careful look16:24
niemeyerTheMue: I love "observices", btw.. we should totally have a place for that somewhere in Juju :-)16:43
TheMueniemeyer: ;)16:43
TheMueniemeyer: funny thought mixup into one word16:44
TheMueniemeyer: should register it as trademark16:44
niemeyerTheMue: +1 :)16:45
niemeyerTheMue: The overall branch looks very nice, btw17:11
niemeyerTheMue: I love how this is evolving17:11
niemeyerTheMue: You have a proper review17:11
niemeyerTheMue: I'll move on and fix the tomb stuff we discussed re. tomb.Dying17:14
TheMueniemeyer: fine, thx17:17
niemeyerTheMue: Please let me know if the review looks sensible to you17:17
TheMueniemeyer: yip, will do, first have to fetch my dinner17:17
niemeyerTheMue: Oh man, if it's late for you that can wait until tomororw17:18
TheMueniemeyer: it's ok, will at least take a look17:43
niemeyerTheMue: Do you want to have a quick look at the tomb changes before they go in?17:53
niemeyerTheMue: Or, would you mind?17:54
TheMueniemeyer: oh, with  pleasure17:54
niemeyerTheMue: Cool, pushing17:54
niemeyerTheMue: https://codereview.appspot.com/598105217:57
TheMue*click*17:57
niemeyerTheMue: As you will have noticed, also renamed ErrStillRunning to ErrStillAlive, as it was off within the naming context17:59
TheMueniemeyer: Yip, seen. Makes sense.18:01
niemeyerTheMue: Have you had a chance to look?18:17
TheMueniemeyer: almost done18:18
niemeyerTheMue: Superb, thanks18:18
TheMueniemeyer: just wanted to get a better insight in tomb.18:21
niemeyerTheMue: That's great for sure18:21
TheMueniemeyer: review is in18:31
TheMueniemeyer: took a look at your review, most parts are ok (even if i still find adding adding an own tom to the ConfigWatcher increases complexity, not much, but it does). and i'll move the ConfigWatcher from service.go to state.go18:32
niemeyerTheMue: Cheers!18:36
niemeyerTheMue: I'll put the defer into that case where the function is a bit more involved18:42
niemeyerTheMue: The other cases don't look necessary18:42
TheMueniemeyer: i like using defer for a linear execution Open()/defer Close(), Dial()/defer Close() etc. Fire and forget, no nesting.18:44
niemeyerTheMue: Yeah, that's cool in many cases.. but when it's a short lived and simple function, the defer is merely overhead18:49
TheMueniemeyer: how much overhead? shouldn't be premature optimization18:51
niemeyerTheMue: This isn't premature optimization.. this is pointless deoptimization.. :)18:51
niemeyerTheMue: It's assignment..18:51
niemeyerIt's an assignment, that is18:52
niemeyerLock; a = t.foo; Unlock18:52
niemeyerTheMue: What are you defering for?18:52
niemeyerTheMue: You're right about Kill, though.. it looks better18:53
TheMueniemeyer: keeping an idiom to establish it more and more so that the code is more maintainable, regardless if the method is a one-liner or more complex18:53
niemeyerTheMue: Lock; trivial; Unlock is a fine idiom too, looks nice, is clean, and happens to use less resources than a defer18:54
niemeyerTheMue: Again, you're right about Kill, though18:55
TheMueniemeyer: ok18:56
niemeyerTheMue: I've updated the code, in case you'd like to look or LGTM it18:57
niemeyerTheMue: Although, it's just your suggestion18:57
TheMueniemeyer: *click* again ;)18:57
TheMueniemeyer: lgtm18:59
niemeyerTheMue: Cheers!19:00
niemeyerTheMue: Thanks for the suggestion as well19:00
TheMueniemeyer: np, my pleasure19:01
TheMueniemeyer: i'm off for today, cu tomorrow19:18

Generated by irclog2html.py 2.7 by Marius Gedminas - find it at mg.pov.lt!