/srv/irclogs.ubuntu.com/2012/11/30/#juju-dev.txt

TheMueGood morning.07:04
fwereadeTheMue, heyhey07:09
TheMuefwereade: Hiya07:09
=== TheMue_ is now known as TheMue
davecheneygood morning gentle ment07:32
davecheneygentlemen07:32
fwereadedavecheney, heyhey07:32
fwereadeTheMue, ok, I am looking in detail at the "firewaller bug"07:33
fwereadeTheMue, have you played around with that at all yourself?07:33
TheMuedavecheney: Good mroning07:33
TheMuefwereade: No, only discussed it so far with Aram.07:34
fwereadeTheMue, can you recall anything specific about how he was characterising it?07:34
davecheneyhttps://codereview.appspot.com/6856120/07:34
davecheney^ version III of cross series bootstapping07:34
TheMuefwereade: It only happened after has change of the firewaller. So maybe it's better to wait until Monday to talk with him about those changes.07:34
fwereadeTheMue, so the answer to the question I asked is "no"? :)07:35
TheMuefwereade: He talked about a kind of race situation, but only in global mode.07:35
fwereadeTheMue, ah, hmm, ok, it looks like I'm stuck on something different then07:36
fwereadeTheMue, I think I fixed that one07:36
TheMuefwereade: Hey, not so fast. I need my time to write here in the bottom line while you're asking new questions above. ;)07:36
fwereadeTheMue, sorry :)07:36
TheMuefwereade: NP, had a smiley at the end. :D07:37
TheMuefwereade: His change after the watcher changed has been to extract a larger part of the firewallers loop code into an own method. But there it works differently, because the lifecycle states of the units returned by the watcher has to be checked.07:38
fwereadeTheMue, ok, I don't *think* that is currently an issue07:39
fwereadeTheMue, I'm pretty certain I have tweaked the firewaller such that it's responding to global mode events nicely07:39
fwereadeTheMue, now I'm confused that a unit watch appears not to be firing when it should07:39
TheMuefwereade: Is it already submitted or a CL?07:39
fwereadeTheMue, thank you for the context though07:40
fwereadeTheMue, it's Arams 120 CL07:40
fwereadeTheMue, that niemeer asked me to finish off and land07:40
TheMuefwereade: You're welcome, I'm interested in it too as the Firewaller has initially been my baby. ;)07:40
TheMuefwereade: Do you please have the URL for me, to quickly jump in?07:41
fwereadeTheMue, I haven't even pushed it yet, just a mo07:41
TheMuefwereade: OK07:41
fwereadeTheMue, hm, sorry, it'll be inconvenient to push right now07:42
TheMuefwereade: OK, I think I get a notification when you'll push it, so then I can jump in again.07:43
fwereadeTheMue, I'm just pushed to lp:~fwereade/juju-core/aram-firewaller-sketch if you want to take a look (and, ideally, paste me the output of TestGlobalModeRestartPorts on your machine?)07:45
fwereadeTheMue, it has a load of random debug prints pooed in there07:45
TheMuefwereade: Yes, one moment.07:46
fwereadeTheMue, heyyyyyyyyy I know what this looks like08:03
fwereadeTheMue, maybe08:03
fwereadeTheMue, if a client asks for a watch on a channel and isn't receiving, it just blocks the whole watcher08:04
TheMuefwereade: So, after the mgo/mongodb update test is running and TestGlobalModeRestartPorts passes w/o any messages. Strange.08:16
fwereadeTheMue, gaah TestGlobalModeRestartPortCounts08:16
fwereadeTheMue, sorry08:16
TheMuefwereade: Passes too, also sorry. ;)08:17
fwereadeTheMue, ok, that's weird :)08:19
TheMuefwereade: Indeed.08:20
rogpeppedavecheney, fwereade, TheMue: morning!08:51
TheMuerogpeppe: Hi08:51
fwereaderogpeppe, heyhey08:51
davecheneymorning all08:52
rogpeppedavecheney: glad to hear the TLS update worked for you...08:54
davecheneyrogpeppe: it's fn' awesome08:57
davecheneyso much faster than ssh08:57
rogpeppedavecheney: i'm a bit surprised by that actually08:58
rogpeppedavecheney: the network latency should be approximately similar08:58
davecheneymuch less round trips08:58
rogpeppedavecheney: to set up the connection?08:58
rogpeppedavecheney: i didn't realise ssh was inefficient that way08:59
davecheney3 round trips for tcp handshake, then a dozen for ssh handshake, then 2 for tcp channel, then the mgo setup on top of that09:05
davecheneyi'd bet pesos to dollars that tls handshaking is more effective than ssh tunneling09:06
rogpeppedavecheney: TLS handshake is standard diffie hellman, i think, which is one round trip. there may be more too though, to negotiate the crypto.09:08
davecheneydepends on the size of the cert09:09
davecheneybut it is much more efficient09:09
davecheneyso, on high latency the difference is remarkable09:09
davecheneyalso, shit: https://code.google.com/p/go/source/detail?r=697f36fec52ceaabc2208d28918fc34787b617bb09:10
davecheneyspent three evenings working on this one09:10
rogpeppedavecheney: ah bugger. what a pity. have you worked out what the problem was yet?09:23
davecheneyissue 59909:25
davecheney64bit atomics need to be 8 byte aligned09:25
davecheneyi should have remembered earlier09:26
fwereaderogpeppe, TheMue: I had believed that the watcher would panic if you tried to unwatch something you hadn't watched... is that not the case?09:34
rogpeppefwereade: you're talking about state/watcher?09:35
fwereaderogpeppe, yeah09:35
rogpeppefwereade: doesn't look like it from a brief glance at the source09:36
rogpeppefwereade: looks like it's idempotent09:36
fwereaderogpeppe, indeed, I just could have sworn it was like that once09:36
fwereaderogpeppe, probably just fever dreams09:36
rogpeppefwereade: it would be an easy change to make09:36
fwereaderogpeppe, indeed, I may mention it to niemeyer09:37
TheMuefwereade: One moment, daughter is here, will be back in a few seconds.09:38
fwereaderogpeppe, TheMue: could I get a trivial +1 on https://codereview.appspot.com/6856122 please?09:38
fwereaderogpeppe, that panicing would have made it *much* quicker to find that issue, I think09:39
TheMuefwereade: *click*09:39
rogpeppefwereade: it's a pity that a document id is an interface{}09:41
rogpeppefwereade: in fact, where do we use a document id that's not a string?09:42
TheMuefwereade: Has the Unwatch() changed to take an id instead of a Life.09:43
rogpeppefwereade: ha, the answer is "nowhere"09:44
rogpeppefwereade: probably that's only since you've changed machine id to string09:44
rogpeppefwereade: that would've caught the problem too09:45
rogpeppefwereade: no, it was just a mistake09:45
rogpeppes/fwereade/TheMue/09:45
TheMuerogpeppe: OK09:45
fwereaderogpeppe, also, relations have an "Id" field that we use internally but a mgo "_id" called Key09:47
fwereaderogpeppe, so, yes from the watcher POV we could still use strings09:47
fwereaderogpeppe, but it's muddy09:48
rogpeppefwereade: all the tests run fine with strings09:48
fwereadeTheMue, the Unwatch never needed a life09:48
rogpeppefwereade: but i see what you mean09:48
fwereaderogpeppe, cool09:48
rogpeppefwereade: could you make a test for this?09:48
fwereaderogpeppe, I broached the subject with niemeyer, he seemed -1 on changing it09:48
rogpeppefwereade: fairy nuff09:48
TheMuefwereade: Yep, I took a look and saw that it only hasn't been catched by the compiler due to the interface{}.09:49
fwereaderogpeppe, that's an interesting philosophical question09:49
fwereaderogpeppe, if I were to write a test for this I would also feel obliged to write a similar one for every watcher09:49
rogpeppefwereade: ha09:49
rogpeppefwereade: maybe you should09:50
rogpeppefwereade: maybe they're broken similarly...09:50
davecheneyrogpeppe: https://codereview.appspot.com/6856120/09:56
rogpeppedavecheney: looking09:58
rogpeppedavecheney: is configTest.series ever going to be set to something other than version.Current.Series?10:00
rogpeppedavecheney: (or "")10:00
davecheneyrogpeppe: yes10:00
rogpeppedavecheney: how so?10:01
davecheneybootstrapping from quantal -> precise10:01
rogpeppedavecheney: so is the plan to add an argument to config.New?10:02
rogpeppedavecheney: thinking about it, i'm not convinced that default-series should default to anything10:03
rogpeppedavecheney: but i'm open to contrary arguments10:04
davecheneyrogpeppe: id' say it should always default to precise10:04
davecheney(insert current LTS release)10:04
davecheneythis is all in aide of https://codereview.appspot.com/6851081/10:04
rogpeppedavecheney: ignoring version.Current.Series?10:04
davecheneyafter a very long talk with gustavo10:04
davecheneyi still have no idea how to test this10:04
davecheneyother than the sledgehammer approaches I have previously suggested10:04
rogpeppedavecheney: i don't think the configTest.series parameter is necessary. you can just test against whatever the default should be, in configTest.check.10:06
rogpeppes/parameter/field/10:06
rogpeppedavecheney: i'll have a think about how you might want to test cross-series bootstrapping10:07
davecheneythanks rogpeppe, i'm really stuck10:07
fwereadebrb10:21
dimiternhey, can I depend on deterministic ordering in slices? (when testing building a slice by appending)10:22
dimiternand what's the best way to test this, given []Type as a result and having another - what type of assert is best?10:23
davecheneydimitern: yes, slice are ordered10:25
rogpeppedimitern: yes10:25
rogpeppeand DeepEquals10:26
rogpeppedimitern: assuming the types are not opaque10:26
dimiternrogpeppe, davecheney: ok, 0x10:26
rogpeppedimitern: have you read this article? http://research.swtch.com/godata10:27
dimiternrogpeppe: what do you mean opaque? no I'll read it now10:29
rogpeppedimitern: i mean you shouldn't use DeepEqual if the values have unexported fields10:29
dimiternrogpeppe: right, that's the case10:30
dimiternrogpeppe: but does it matter, since the're all in the same package?10:30
rogpeppedimitern: it depends what kind of equality you're interested in10:30
rogpeppedimitern: what are you actually trying to assert?10:31
dimiternrogpeppe: well, I have AllFlavors() call, which returns []Flavor and error, and I called AddFlavor() twice with fl1, fl2, and now it seems []Flavor{fl1,fl2} != the result, but maybe I'm returning them in reverse order10:32
davecheneydimitern: if your flavors live in a map10:33
davecheneypossibly10:33
rogpeppedimitern: i didn't realise a Flavor had unexported fields10:33
dimiterndavecheney: yes, I have map[string]Flavor10:33
davecheneyso if you're doing something lie10:33
davecheneyfor k, v := range flavors { if k == "something" { append(...) } }10:34
davecheneythen the order your iterate over flavors is random10:34
dimiternrogpeppe: it's a local type, Flavor has entity *nova.Entity and detail *nova.FlavorDetail - one or both can be specified10:34
dimiterndavecheney: ok, is there something similar to pythons's dict.values(), without iterating over the map?10:35
rogpeppedimitern: it sounds like DeepEqual might be appropriate in this particular case.10:35
davecheneyrogpeppe: isn't there a SliceEquals or something ?10:35
davecheneyfor set equality ?10:36
dimiternrogpeppe: tried DeepEquals, but does not work if the order is different10:36
dimiterndavecheney: not sure, I'll try10:36
rogpeppedavecheney: i don't think so10:36
davecheneyshitter10:37
rogpeppedimitern: one conventional way of doing this is to sort the slices before comparing them10:37
dimiternrogpeppe: how?10:37
dimiterndavecheney: no, SliceEquals does not exists10:37
rogpeppedimitern: look at the sort package, define Less, Swap and Len methods on a new type sortedFlavors []Flavor10:37
rogpeppedimitern: (one line each)10:38
dimiternrogpeppe: ok, I'll check it out10:38
rogpeppedimitern: then sort each slice, by type-converting it to sortedFlavors, then use whatever equality operation you feel is appropriate10:38
dimiternrogpeppe: that seems like a lot of work to compare 2 slices - how about just iterating over them and checking each10:40
rogpeppedimitern: it's probably more work to do that, tbh10:41
rogpeppedimitern: defining the sort methods is mechanical and easy10:42
rogpeppedimitern: because you don't just want to declare two slices10:42
rogpeppedimitern: you want to make sure they're exactly the same10:42
dimiternrogpeppe: I'm looking at the sort pkg now10:43
rogpeppedimitern: regardless of order10:43
rogpeppedimitern: tbh, if you're adding your own flavors and checking them, it's probably overkill to check the whole Flavor10:44
dimiternrogpeppe: the docs for Soft says: The sort is not guaranteed to be stable. - what's that?10:44
rogpeppedimitern: it means that equal items won't necessarily end up in the original order10:44
rogpeppedimitern: you could just check some aspect of it that you know about10:44
rogpeppedimitern: e.g. a name10:44
dimiternrogpeppe: exactly, I have only 2 items and they can have at most 2 orderings10:45
rogpeppedimitern: in which case, you could just compare and swap, then DeepEqual10:45
rogpeppedimitern: same difference10:45
dimiternrogpeppe: yep, that seems the easiest10:45
rogpeppedimitern: if even, just compare the first element of each slice, then swap one if they're different, then compare both slices10:46
rogpeppes/if even/or even/10:46
dimiternrogpeppe: yeah, this works and since it's a simple case I'll leave it to this10:46
dimiternmgz: or w7z: ?11:00
mgzhey dimitern11:01
dimiternmgz: hey :) i was not sure which one you're watching - mumble?11:01
mgznearly there, left my headset somewhere silly...11:02
dimiternwallyworld: ^^11:05
wallyworldok11:05
fwereaderogpeppe, TheMue: I've updated https://codereview.appspot.com/6856122 -- it should still be pretty trivial11:17
TheMuefwereade: Already lookin' ;)11:17
fwereaderogpeppe, TheMue: the watcher package change means that the MUW tests fail reasonably comprehensibly when the dont-unwatch-life-values fix11:17
fwereade...is not there11:18
TheMuefwereade: Aaaaah, that's what missing, just wanted to ask.11:19
rogpeppefwereade: LGTM11:21
fwereaderogpeppe, awesome, thanks11:22
fwereaderogpeppe, I'm printing the channels because it really helped me to be able to just print suspicious-looking channels when I watched, and that was very useful in the early stages when I was still zeroing in on a fix11:24
fwereaderogpeppe, it may not be so useful now, i guess11:24
fwereaderogpeppe, thanks11:24
rogpeppefwereade: i think that if you're debugging, you'll add prints where necessary. an isolated channel pointer print isn't much help really.11:24
fwereaderogpeppe, the isolated panic is kinda handy though, because you can just put your prints in state/watcher and not have to worry about understanding the watcher package11:26
rogpeppefwereade: true, the channel is an external thing, isn't it. fair enough, why not leave it?11:26
fwereaderogpeppe, cheers11:27
fwereadeTheMue, any comments?11:28
TheMuefwereade: You'll get your LGTM in a few moments. ;)11:28
fwereadeTheMue, <311:29
TheMuefwereade: You've got it.11:31
fwereadeTheMue, the channel pointer print is the difference between (1) debugging by sprinking a few prints in state/watcher.go (or whatever the client is) and (2) opening up and coming to understand the watcher package well enough to determine that you need to print the channels around the pointw where I panic11:35
fwereadeTheMue, and (2) also includes all of (1)11:35
fwereadeTheMue, as rogpeppe pointed out, the channel is a watch param just like coll and id11:35
fwereadeTheMue, revno is not interesting here, so I didn't print that11:36
fwereadeTheMue, but the specific channel *is* interesting, because the watcher can have N watches for a given key11:36
fwereadeTheMue, and the challenge becomes figuring out which watch is unmatched11:36
fwereadeTheMue, do you still object to panicing with the chan?11:37
fwereadeniemeyer, heyhey11:38
niemeyerGood morning!11:39
TheMuefwereade: OK, reasonable.11:39
fwereadeTheMue, cheers11:39
TheMueniemeyer: Hiya.11:39
rogpeppeniemeyer: morning!11:40
niemeyerfwereade, TheMue, rogpeppe: Heyas!11:40
jammgz, dimitern, wallyworld: Something landed recently in trunk broke the build: https://pastebin.canonical.com/79484/11:54
jamwallyworld: I think it was your change to return 'nil' for objects when there has been an error.11:54
wallyworldyes :-(11:55
jamIf we want to keep 'nil', we need to change the return to "*Object" rather than "Object"11:55
jamsince pointers can be nil11:55
jambut a struct cannot.11:55
wallyworldhmmm. i guess that's the correct thing to do11:55
jamwallyworld: but also note, I'm not sure that adding the 'if' statement *improves* the code.11:55
jamwallyworld: I tried sending an email this morning, and tried again just now.11:55
wallyworldi was doing what the code review called for11:55
wallyworldlet me check, i missed the email11:56
jamwallyworld: Oh, I understand that, I'm disagreeing with rogpeppe not you. I approved your change, but questioned the motive.11:56
wallyworldmaybe i need to return an empty struct?11:56
jameven with that, we should be careful to run 'go test ./...' before committing on trunk, since we don't have a bot yet.11:56
wallyworldyeah, sorry11:56
wallyworldi thought i had but clearly not11:56
jamwallyworld: IMO, returning an empty struct is just as bad as a partial one. Since they have an object that is 'valid'.11:57
jamIn which case, just return what you have, and set err like you were doing.11:57
jamOr, we change everything to pointers.11:57
jamanyway, i'm not really working today11:57
jam:L)11:57
wallyworldyour preference?11:57
jam:)11:57
rogpeppejam: was that the named-return-variable discussion?11:57
jamwallyworld: *mine* is to not repeat the if err != nil, check in the function, that the callers are going to have to do anyway.11:57
jamrogpeppe: sorry, I do want to discuss this, but my son needs to play Lego Batman... :)11:58
jamCan we chat maybe later, or on Monday/Tues?11:58
rogpeppejam: nananananananana batman!11:58
rogpeppejam: sure11:58
wallyworldjam: i'll fix the build and we can discuss next week11:58
niemeyerwallyworld: If in doubt, I'd suggest returning a pointer12:15
niemeyerwallyworld: That's appropriate in most cases12:16
niemeyerwallyworld: Of course, and returning nil consistently when err != nil12:16
wallyworldniemeyer: for now, i'm just reverting the changes to fix the breakages, and will tackle properly next week once we have consensus12:16
wallyworldsince it's late here now and i'm tired12:16
niemeyerwallyworld: Sure, I'm just saying this is a well known concept12:16
niemeyerwallyworld: If you go over existing code, both ours and upstream, you'll see a clear pattern12:17
wallyworldjam makes a good point though about the functions doing their own if err != nil checks12:17
rogpeppewallyworld: it's definitely conventional to return a zero value when err != nil, pointer or not. that was the reason for my comments.12:17
wallyworldagree pointer is best12:17
niemeyerYes, and returning partial data when err != nil is not okay12:18
wallyworldi wonder, if err != nil, why does the returned value need to be zero?12:18
wallyworldwouldn't it be ignored anyway?12:18
niemeyerThere are very rare exceptions to this rule, which confirms the rule.. Those are related to cases where it's important to observe the partial values, and the partial values are deterministic in such cases.12:19
wallyworldit seems like it's just adding complexity12:19
wallyworldlots of apis in other languages say, if there's an error, such and uch is undefined12:19
niemeyerwallyworld: It's one more layer to prevent bad usage12:19
niemeyerwallyworld: yes, that's not the case here12:20
niemeyerwallyworld: We consistently return a zero value when errors are found12:20
wallyworldok. it costs to do that though12:20
niemeyerwallyworld: I haven't spent much so far :)12:20
wallyworldwell, each api call needs repetitive blocks of code "if err != nil ..."12:21
wallyworldmakes it messy, especially if the caller also does "if err != nul..."12:21
niemeyerwallyworld: We do err != nil all the time12:21
niemeyerwallyworld: It's pretty clear and cheap12:21
wallyworldso we have 2 places doing the error checking - the caller and the callee12:21
rogpeppewallyworld: you only need that if you're returning something that may not be zero12:22
niemeyerwallyworld: We have tons of places doing error checking12:22
rogpeppewallyworld: in the case we're talking about, we were returning a value that may or may not have been partially filled in12:22
wallyworldwhat if the semantics of the call say - "if there's an error, don't use the returned vsalue"12:22
niemeyerwallyworld: That's not even on the list of things that actually burned my own time over the past few years12:22
niemeyerwallyworld: That still wouldn't change the fact that there's a strong convention that is useful as it prevents crack from flowing through12:23
wallyworldok, no problem. it does seem like code duplication for little gain, but that's just IMO :-)12:24
wallyworlds/code duplication/excessive boiler plate12:24
niemeyerwallyworld: I'd appreciate seeing an example12:24
niemeyerwallyworld: Of what you claim is code duplication12:24
wallyworldok, i'll do a pastebin12:24
niemeyerwallyworld: Doing if err != nil { return nil, err }, or doing if err != nil { return foo, err }12:25
niemeyerwallyworld: Doesn't really cost much, and the former one is both less error prone, and more clear in intention12:25
rogpeppeniemeyer: in this case, i think it was between: if err != nil { return nil, err }; return foo, nil;  and a plain return.12:26
wallyworldhttps://pastebin.canonical.com/79488/12:27
wallyworldsee how the caller and calle both do the if err != nil12:27
wallyworldthe function has no need to12:27
wallyworldif just clutters the code12:27
wallyworldwhy not just return data, err12:27
wallyworldwho cares if data is partially populated, err will tell that something is wrong and not to use it12:28
niemeyerwallyworld: pastebin.ubuntu.com is a better one for that12:28
niemeyerwallyworld: As it's public12:28
wallyworldok, old habits12:28
niemeyerwallyworld: Let me grab my second factor auth key :)12:28
wallyworldsorry12:28
niemeyerwallyworld: No worries12:28
wallyworldthe private one is in my browser history12:29
wallyworldso, my view is that normally, the function semantics of such things normally are such that if an exception is raised, or an error returned, disregard any result data12:29
niemeyerwallyworld: It's hard to follow that example, as it contains completely invalid code12:30
wallyworldsorry, it's pseudo code cut and pasted from real code12:30
niemeyerwallyworld: Yeah, but it's completely broken, badly intended, and referring to variables that don't even exist12:30
wallyworldsure, but that doesn'tmatter for the sake of the argument12:31
niemeyerwallyworld: You won't convince me about how I'm wrong about things being error prone and trivial with such an example :-)12:31
wallyworldthat take awaya is12:31
wallyworldif err != nil {12:31
wallyworld    return nil, err12:31
wallyworld}12:31
wallyworldreturn resp.Images, nil12:31
wallyworldthe above is from the function12:31
niemeyerresp doesn't exist on that context12:31
wallyworldwhy does it need to do the if err != nil12:31
wallyworldwhy not just return resp.IMages, err12:32
wallyworldand let the client do if err != nil12:32
niemeyerwallyworld: Sorry, I honestly can't suggest anything.. the example is completely broken. I'm arguing that this is trivial to write, and that it makes code less error prone. Hard to even make the point if the example is completely crackful.12:32
wallyworldhere's the full function, i was hoping you could just see the intent from the pseudo code, http://pastebin.ubuntu.com/1398973/12:33
wallyworldimagine a module with dozens of such functions, all doing if err != nil unnecessarily, sure adds a lot of bloat and boilerplate12:34
wallyworldwhen the caller just goes ahead and does the err != nil dance anyway12:34
rogpeppewallyworld: that's a pretty unusual case actually12:34
rogpeppewallyworld: because it's not returning something that something else returned.12:35
rogpeppewallyworld: it's returning something that something else might or might not have filled in12:35
wallyworldyes true12:36
wallyworldand the err tells us if the fill in worked12:36
rogpeppewallyworld: agreed. we *could* just allow arbitrary broken return values when err != nil12:36
niemeyerwallyworld: That's fine, as long as there's a promise from the underlying function to never touch the resp value if any errors are returned12:37
wallyworldthat's a pretty standard semantic12:37
rogpeppewallyworld: but i think it's nicer if we do things more predictably12:37
niemeyerwallyworld: I'd be slightly surprised if that promise is in place, though12:37
wallyworldi agree it's nicer perhaps, but at the cost of a fair bit of bloat12:37
niemeyerwallyworld: Because it means you cannot return any errors after resp has been touched12:37
niemeyerwallyworld: That seems the heart of your concern12:38
rogpeppewallyworld: tbh, i think the "bloat" makes the code easier to read12:38
niemeyerwallyworld: And honestly bloat to me is something else..12:38
wallyworldi guess i see cut and paste boilerplate as bloat12:38
rogpeppewallyworld: it means that i *know* instantly the set of possible values returned by ListImagesDetail12:38
niemeyerwallyworld: I see logic that is hard to read, poorly engineered, hard to maintain, as bloat12:39
niemeyerwallyworld: Error prone as well.. totally bloatful12:39
wallyworldsure, there's more than one type of bloat12:39
wallyworldi'll point jam to the scrollback when he is next in the office, since he also shared my concerns12:40
niemeyerwallyworld: That trivial line, makes things lighter to process.. I know I don't have to worry about the return value having bad data, and I know any callers couldn't *possibly* use a partial value coming out of it. It empties brain space rather than filling it up.12:40
wallyworlds/line/lines :-P12:41
wallyworldthanks for the discussion though12:42
wallyworldinteresting points of view12:42
niemeyerwallyworld: Exactly my point.. 10 lines of code may be easier to read than 1.12:42
wallyworldmaybe, depends on the reader i guess12:43
niemeyerwallyworld: Depends on the lines of code12:43
wallyworldor more so one's unerlying expections about the semantcs of the call12:44
wallyworldas a caller, i would never dream of using returned data if err != nil12:44
niemeyerwallyworld: I'm glad to hear that.12:44
wallyworldso it never would enter my head to expect the function to have to do anything about it12:44
niemeyerwallyworld: That still doesn't mean that you won't do that anyway, by mistake.12:45
niemeyerwallyworld: Either way, if the point isn't easy to agree with, I ask that we at least sustain that strong convention that we use both internally, and externally in the core Go development team.12:45
wallyworldsure, no problem12:46
wallyworldi was trying to understand the underlying rationale12:46
niemeyervar foo []Foo12:46
niemeyerfoo, err = Func()12:46
niemeyerif err == ErrSomething {12:46
niemeyer    // Ah, okay, that error is expected here.12:47
niemeyer}12:47
niemeyerOops.. foo has bad data now.12:47
wallyworldyes, and so don't use it12:47
niemeyerwallyworld: Yeah, you're very smart and will never do that. I'm kind of dumb, and tend to make mistakes.12:47
wallyworldhey, i didn't mean it like that12:48
wallyworldtests are also part of the solution too12:48
niemeyerwallyworld: They surely are. Not rare we assert the fact we get a zero value, for example.12:50
fwereadeniemeyer, aram's firewaller change is up again at https://codereview.appspot.com/684312812:51
wallyworldanyways, i'll make the necessary changes to use pointers12:51
niemeyerfwereade: I'll get on it right now12:51
fwereadeniemeyer, the firewaller bug was a MachineUnitsWatcher bug, fixed this morning12:51
wallyworldso the pattern will work as intended12:51
niemeyerfwereade: Oh, what was it about?12:51
fwereadeniemeyer, we were unwatching the wrong key12:51
niemeyerwallyworld: Thanks a lot12:51
niemeyerwallyworld: and thanks for explaining your POV12:51
wallyworldnp, thanks for the discussion12:51
fwereadeniemeyer, state/watcher now panics if you try any funny business like that12:51
niemeyerfwereade: Holy crap, the wrong key huh12:52
fwereadeniemeyer, `for _, unit := range map[string]Life{...} {`12:53
niemeyerfwereade: Woah12:53
fwereadeniemeyer, quite so12:53
niemeyerfwereade: I think I did that before too.. will pay more attention to ranges12:53
fwereadeniemeyer, took a while to track it down, it doesn't exactly leap out at you when the type is defined elsewhere12:53
TheMuelunchtime, biab12:54
niemeyerfwereade: It didn't help that Unwatch takes an interface to support keys of multiple types12:56
niemeyerTheMue: Enjoy12:56
fwereadeniemeyer, yeah, indeed12:56
fwereadeniemeyer, rogpeppe pointed out that all our _ids are actually strings now12:56
fwereadeniemeyer, although I'm still really bothered by id/_id on Relation12:57
niemeyerfwereade: Well, we could have saved ourselves the trouble if the watcher was at least verifying basic typing12:57
niemeyerfwereade: string/int/int64...12:57
niemeyerfwereade: Do you have an idea to workaround it?12:58
fwereadeniemeyer, only that we could change it to demand string ids right now and I think everything would still work12:58
fwereadeniemeyer, but tbh the panicing seemed to do the trick well enough12:59
niemeyerfwereade: Have you gone through the firewaller logic, or just reinstated the original branch?12:59
niemeyerfwereade: I don't understand how that would solve the id/_id case12:59
fwereadeniemeyer, I have made slight enhancements to what existed but have not 100% verified everything from the ground up -- but 3 of us have already done so AIUI12:59
fwereadeniemeyer, oh, it wouldn't at all12:59
fwereadeniemeyer, it's just that I'm reluctant to start making pronouncements about "id"s wen I am still regularly tripped up by the relation id/key thing13:00
niemeyerfwereade: You could invert the relationship again by doing an extra lookup13:01
fwereadeniemeyer, the id/key one? sorry, I don;t follow13:02
niemeyerfwereade: That said, how to guarantee uniqueness would still bother13:02
niemeyerfwereade: Yes13:02
niemeyerfwereade: I'm talking about the reason why we have key in _id13:02
fwereadeniemeyer, ah, ok, I see -- we can't enforce uniqueness on additional fields then?13:03
niemeyerfwereade: We can create additional unique indexes on another field13:03
niemeyerfwereade: But it's an extra index, and the txn package works against _id13:03
niemeyerfwereade: We could disable the auto-index creation, create an additional unique index on key, and change the txn package to support other fields13:04
niemeyerfwereade: But, where's the gold at the other side of the rainbow?13:05
fwereadeniemeyer, I'm sorry, I don't see where the txn package changes come in13:05
niemeyerfwereade: The Id field is mapped on _id13:06
niemeyerfwereade: All of the transactioned operations, inserts, updates, removes, are done against _id13:06
fwereadeniemeyer, ok -- but both "id" and "_id" would still have to be unique, so surely we could still do the same against _ids that looked like "0" or "198" just as easily as ones that look like "wordpress:db mysql:server", couldn't we?13:07
fwereadeniemeyer, and we look up by both key and id, so we really ought to be indexing on key anyway13:08
fwereadeniemeyer, sorry, "id"13:08
rogpeppeniemeyer, fwereade, TheMue: i'm going for lunch now. i will be working this afternoon, but maybe not online all the time as i'll be on the road.13:08
niemeyerrogpeppe: Cool, have a good one13:09
niemeyerfwereade: Uniqueness against 0 or 198 don't mean anything.. we create those numbers to be unique13:09
fwereadeniemeyer, the only other change I can think of is in the check-by-prefix in ServiceRelationsWatcher, and that's just a field switch... right?13:09
niemeyers/don't/doesn't13:09
fwereadeniemeyer, will the txn package somehow be able to insert docs with duplicate keys in the face of uniqueness constraints?13:10
niemeyerfwereade: Well, the underlying db doesn't allow it13:12
fwereadeniemeyer, ah! but it will break txn.DocMissing?13:13
niemeyerfwereade: DocExists, DocMissing, yes13:14
* fwereade sees now13:15
fwereadeniemeyer, yeah, probably worth the localised confusion then :)13:15
niemeyerfwereade: Hah, funny.. the fictitious err-related example I mentioned above using a zero-value on err != nil exists on this branch. :-)13:19
fwereadeniemeyer, oh, poo, what did I do?13:25
niemeyerfwereade: Uh, nothing bad? :)13:25
fwereadeniemeyer, ah? sorry, I thought you were pointing out a mistake13:25
niemeyerfwereade: No, I was pointing out earlier that it's important to be consistent on the zero-value on errors convention13:26
fwereadeniemeyer, definitely -- and I guess aram or I did so? :)13:26
niemeyerfwereade: and as one example I used a snippet, (HH:46, above)13:26
niemeyerfwereade: That snippet exists almost as-is in the branch13:26
niemeyerfwereade: It would be a bug if the convention wasn't respected13:27
fwereadeniemeyer, ah, yes, indeed13:27
niemeyerfwereade: Very nice13:30
fwereadeniemeyer, cheers :)13:31
niemeyerfwereade: Thanks a lot13:31
fwereadeniemeyer, np at all13:31
fwereadeniemeyer, ah HA: there is *also*, it appears, a firewaller bug, that I had hitherto failed to repro13:41
fwereadeniemeyer, I shall meditate upon this13:41
niemeyerfwereade: Hm13:41
niemeyerfwereade: How did you figure?13:41
fwereadeniemeyer, I saw a test failure :/13:42
niemeyerfwereade: Oh13:42
fwereadeniemeyer, in TestGlobalModeRestartPortCount, as flagged :(13:42
fwereadeniemeyer, I'm just about to investigate after I propose a trivial fix to UnitsWatcher -- I mistakenlythought I didn't want to notify Dead units in the initial set, but I was wrong13:44
niemeyerfwereade: Oh?13:44
niemeyerfwereade: Ah, I think I see13:45
fwereadeniemeyer, they get lost from view if they're dead when we start up13:45
fwereadeniemeyer, generally we need to handle dead ones13:45
fwereadeniemeyer, I *could* do it by reconciling against what's installed but htat actually just feels like needless complexity13:45
niemeyerfwereade: Agreed, I think it's fine to report13:46
fwereadeniemeyer, we can do it differently if you don;t like Deployer (which I will get to one day ;p)13:46
fwereadeniemeyer, cool13:46
niemeyerfwereade: We can make it respect the Dead-is-the-last-thing-seen idea13:46
fwereadeniemeyer, ah, I can't reconcile anyway13:46
fwereadeniemeyer, exactly, it is still respected13:46
fwereadeniemeyer, https://codereview.appspot.com/684613313:48
niemeyerfwereade: We don't send dead statuses, strictly speaking13:49
* niemeyer thinks13:50
niemeyerfwereade: "Once a unit observed as Dead has been reported" perhaps13:50
fwereadeniemeyer, SGTM, thanks13:51
niemeyerfwereade: LGTM, cheers13:53
fwereadeniemeyer, "as Dead or removed"?13:54
niemeyerfwereade: +113:55
fwereadeniemeyer, cheers13:55
* niemeyer => lunch14:05
TheMueniemeyer: Enjoy14:09
TheMue*: Any experiences with OAuth packages around?14:14
rogpeppeTheMue: which version?14:17
TheMue*: Will start with goauth2 by Andrew.14:17
rogpeppeTheMue: istr that oauth2 is quite different from oauth, but otherwise i know very little14:17
TheMuerogpeppe: Ah, good hint. The Py version uses a package named oauth. Will take a look which version it supports.14:18
TheMuerogpeppe: Seems to be v1.14:21
fwereadeTheMue, may I share your wisdom re firewaller?14:50
fwereadeTheMue, I can't quite figure out whether the bug is in the FW or the test14:51
TheMuefwereade: I'm listening.14:51
fwereadeTheMue, ok, so, the test is problematic14:52
fwereadeTheMue, in that it starts a new FW, and asserts that the opened ports are the same as before14:52
TheMuefwereade: Which test do you refer to?14:53
fwereadeTheMue, and so that test actually finds the expected state before the FW has even had a chance to open or close anything14:53
fwereadeTheMue, TestGlobalModeRestartPortCount14:53
fwereadeTheMue, the problematic one14:53
TheMuefwereade: OK, open it in the editor.14:53
fwereadeTheMue, ok, so the last 4 blocks are a problem14:54
fwereadeTheMue, the assert in the first one is likely to pass regardless of state14:54
fwereadeTheMue, and when the test subsequently passes, the actual timing of the changes is a bit suspect -- initial events are still being handled after port 8080 is closed14:57
fwereadeTheMue, and *at the moment* this is passing reliably for me, butthis is more likely a happy accident of logging than anything else14:57
fwereadeTheMue, I can make the test 100% reliable, with event handling happening at the times I expect, by opening another port somewhere before starting the FW; and waiting for *that* port to be opened14:58
TheMuefwereade: I'm gong through it step by step now.14:59
fwereadeTheMue, http://paste.ubuntu.com/1399817/ and http://paste.ubuntu.com/1399818/ might help you to visualize15:01
* rogpeppe is looking at a beautiful frosty sunset while cruising down the A1. the joys of mobile connectivity.15:01
fwereadeTheMue, === signals event in the main loop; +++ signals port refcount ++, --- signals ports refcount --15:01
TheMuefwereade: Ah, good.15:02
fwereadeTheMue, the first is what we get normally; the second is what we get if I force the test to wait for the correct ports15:02
fwereadeTheMue, I *think* it should always look like the second15:03
fwereadeTheMue, *but* I don't see how that's possible in general, because (as you can see) the events coming in willy-nilly seem to cause surprising refcounts in the first15:05
fwereadeTheMue, ie we never see a refcount of 2 for tcp:80 in the first paste, and ISTM that we should15:07
TheMuefwereade: Yes, I'm wondering.15:07
TheMuefwereade: That's what Aram called the race situation of overlaying changes incrementing and decrementing the refcount at once.15:10
fwereadeTheMue, I would have expected the initial state to be built from initial events, so I'm having a little trouble following how the state built up in initGlobalPorts fits in with the watchery state15:10
TheMuefwereade: The initial one is build by taking a look at the state.15:11
fwereadeTheMue, yeah, that is clear -- but AFAICT it doesn't necessarily correspond with the state picture that will be built up by the watchers15:12
fwereadeTheMue, and I can't see how you reconcile them15:12
TheMuefwereade: One moment, I have to look on my own how we've done it.15:14
TheMuefwereade: It's the first filter part of flushGlobalPorts()15:18
TheMuefwereade: Here toOpen and toClose are only set if they are not only opened or closed.15:18
TheMuefwereade: And in closing, when the refcount is 0, it will be closed.15:19
TheMuefwereade: One has to look exactly when globalPortOpen (a map of port to bool) and globalPortRef (a map of port to int) is used.15:20
fwereadeTheMue, ok, but globalPortOpen is initialized in initGlobalPorts while globalPortsRef is not15:24
TheMuefwereade: Yes, because otherwise each port would be counted twice, once by the state reading, once by the intial events.15:25
fwereadeTheMue, ok -- and it's not ever possible to get a machine thinking it should close a port that was never open?15:26
fwereadeTheMue, (according to globalPortsRef, that is)15:27
TheMuefwereade: So while the initGlobalPorts() just ensures that the ports aren't closed and immediatelly reopened the initial events ensure the correct counting (so far the idea).15:27
fwereadeTheMue, ok, so there's no way an initial event can have the effect of closing a port? but that can't be true15:29
TheMuefwereade: "not ever possible" are big words. ;) Have to check it. But closing in global mode is done when ref == 0 and a close event is raised.15:29
fwereadeTheMue, sure, I can see that15:29
fwereadeTheMue, ok, thought experiment15:30
TheMuefwereade: I'm thinking about enqued event while the state scanning is in progress.15:31
fwereadeTheMue, doing that would make me much more comfortable15:31
fwereadeTheMue, but let's see: 1 machine, with 2 units on it15:31
fwereadeTheMue, one of the units has port 80 open15:32
fwereadeTheMue, a FW starts up and scans this state correctly15:32
fwereadeTheMue, port 80 is true in globalPortsOpen, and is 0 in globalPortRef15:33
fwereadeTheMue, and the FW then starts up its watches15:33
TheMuefwereade: Exactly, and now the initial watcher event is retrieved.15:33
fwereadeTheMue, it gets an event for the machine, and starts a watch for its units15:34
fwereadeTheMue, it then gets an event with the two units in15:34
fwereadeTheMue, and starts port watches for each15:34
fwereadeTheMue, at this precise moment, the unitds think they have no open ports, right?15:35
fwereadeTheMue, so what happens when we get the first port event depends on which port watch happens to fire first15:36
TheMuefwereade: Important is, what the fw thinks. And it thinks, hey, I have the port open, but I don't know how often. But it gets the number by the incoming events.15:37
TheMuefwereade: But you're right, the watcher for the machines units is started after the machine event. And so the state could have been changed inbetween.15:37
fwereadeTheMue, ok, actually, it can be simpler I think15:38
TheMuefwereade: The machine watcher is started before (!) the initial state scanning, so here it's better,15:38
fwereadeTheMue, exactly: if the unit with 80 open closes it after the inital scan and before the watch, port 80 will never be mentioned and never be closed15:38
fwereadeTheMue, it'll be open forever with refcount 015:39
TheMuefwereade: As a first thought I would say you're right.15:40
TheMuefwereade: The delay until the machined is started ...15:40
TheMuefwereade: It seems like initGlobalMode() should start the needed machined immediately.15:41
fwereadeTheMue, if we could do that, that would be great15:41
fwereadeTheMue, it could be fiddly though15:42
TheMuefwereade: And the initial event of the machines watcher has to compare if the started ones are still correct.15:42
TheMuefwereade: Yes, not trivial.15:43
fwereadeTheMue, I don't see any way for it to be correct without doing so though15:43
TheMuefwereade: Based on our current analysis I have to agree, yes.15:43
fwereadeniemeyer, ok, I think TheMue and I are in agreement that there is a fundamental race in the firewaller, which is not trivial to resolve15:47
niemeyerfwereade: Oh15:47
fwereadeniemeyer, I am not intrinsically opposed to diving in and fixing it, but I am reluctant to allow it to delay subordinates15:48
niemeyerfwereade: What's it?15:48
fwereadeniemeyer, basically it (1) builds up a bunch of reference state and (2) starts a bunch of watches to fill in the details of that state15:49
fwereadeniemeyer, but neglects to take account of possible changes in between (1) and (2)15:49
niemeyerfwereade: Ok15:49
niemeyerfwereade: How could this take place?15:49
fwereadeniemeyer, well, initGlobalMode just does a straight scan of state; the main loop then starts building up a huge tree of watchers, starting from the machines and adding units and services as events dictate15:51
niemeyerfwereade: Okay15:51
fwereadeniemeyer, I don't think it'll be *toooo* hard to do it right, but it will definitely be fiddly15:52
niemeyerfwereade: Sorry, I still don't perceive the issue15:52
niemeyerfwereade: Can you walk through the error happening?15:52
fwereadeniemeyer, one machine with one unit; port 80 is open on the unit and in the environment15:53
fwereadeniemeyer, FW does initial scan15:53
fwereadeniemeyer, unit closes port 8015:53
niemeyerfwereade: Ok15:53
niemeyerfwereade: Ok15:53
fwereadeniemeyer, Fw gets its initial machines event, and gets/watches unit state15:54
niemeyerfwereade: Okay15:54
fwereadeniemeyer, the initial state reported is "no ports open"15:54
niemeyerHmm15:54
* niemeyer looks at the code15:54
fwereadeniemeyer, we're watching a unit we got via the machine's units event, not the one we originally looked at to determine that 80 was open15:55
niemeyerfwereade: The set of ports that are actually opened is obtained within the unit watch, when the even fires, right?15:56
niemeyerOh, no15:56
fwereadeniemeyer, ok, what happens is:15:56
fwereadeniemeyer, the firewaller never sees a change to port 80, and hence never closes it15:56
fwereadeniemeyer, ...that's it15:57
fwereadeniemeyer, there's a refcounting mechanism that works fine (I think) when state doesn't change during that critical window15:59
niemeyerfwereade: Where is the window in the code?16:00
fwereadeniemeyer, from the end of fw.initGlobalMode() to the end of the last event on the ports channel that is traceable to the initial machines event16:01
fwereadeniemeyer, I think16:01
fwereadeniemeyer, ok, they all are16:01
fwereadeniemeyer, the last initial event that is itself a conseqence only of initial events, sharing the ultimate ancestor of the first machines event16:02
fwereadeniemeyer, I don;t think I made that any clearer, did I?16:02
niemeyerfwereade: No, but I blame my question16:03
fwereadeniemeyer, ok, looking just at the main fw loop16:03
fwereadeniemeyer, first of all we set up initial state, and then we start paying attention to a pre-started global machines watch16:04
niemeyerfwereade: Perhaps I should try to point out how I originally imagined this would work16:04
fwereadeniemeyer, changes on that are safe16:04
niemeyerfwereade: So you can fix my assumption with reality16:04
fwereadeniemeyer, ok, go for it16:04
niemeyerfwereade: There's an initial pass at the beginning which verifies what is *actually* open in the environment16:06
fwereadeniemeyer, ie according to the provider?16:06
niemeyerfwereade: Yes16:06
fwereadeniemeyer, ok, ty, carry on, this is accurate16:07
niemeyerfwereade: Okay, I think I see the problem actually16:08
niemeyerfwereade: No, wait, okay16:09
niemeyerfwereade: Nevermind, I do see the issue.. closing is indeed a problem because the initial state isn't connected to the initial referenced state16:10
niemeyerfwereade: Open works under the same circumstances, though16:10
niemeyerfwereade: Makes sense?16:10
fwereadeniemeyer, agreed, open is safe16:10
fwereadeniemeyer, except, I *think* there is another issue16:11
fwereadeniemeyer, but I need to think it through a bit16:11
fwereadeniemeyer, gaah it seems not to be flowing16:12
fwereadeniemeyer, the trouble is fundamentally that (1) changes can come in and change state both before and during the watch-scan, and this is confusing and (2) there is a failing test that demonstrates weird refcounts while this is happening, even if it doesn't always fail, and which is fixed by delaying the external changes until we;re sure the FW has finished what it's doing16:14
niemeyerfwereade: I think the issue is rather simple, actually16:15
fwereadeniemeyer, I am sadly not able to actually hold the whole thing in my head atm, so I can't come up with a good explanation of why the test sometimes fails: adding logging seems to have fixed it16:15
fwereadeniemeyer, I am talking here in a very narrow context16:16
* TheMue is playing with the idea of always start the watcher goroutines based on the initial state before retrieving the first machines watcher events.16:16
niemeyerfwereade: I suggest trying to address the actual issue we do know about first16:16
fwereadeniemeyer, that issue only came to light because of the more fuzzily specified one I just mentioned16:16
fwereadeniemeyer, there's a test that fails sometimes16:17
niemeyerfwereade: Cool, I'm glad you did look at this16:17
fwereadeniemeyer, there's an issue in the watcher16:17
niemeyerfwereade: Hm?16:17
fwereadeniemeyer, the two may be connected16:17
fwereadeniemeyer, I am not equals to the task of concretely demonstrating such a connection without handwaving16:17
fwereadeniemeyer, well, I tried to repro it, and I could, and I found the MUW unwatch bug16:18
niemeyerfwereade: That's fine, I'll try to interpret the hand-wavy frequency :)16:18
fwereadeniemeyer, in the following test runs, the firewaller appeared to be fine16:18
fwereadeniemeyer, some time after submitting, I saw the test fail16:18
fwereadeniemeyer, it is irritatingly elusive, and currently appears to be passing 100% for me with no changes otherthan logging16:19
fwereadeniemeyer, but sometimes it fails every 2 or 3 goes16:19
niemeyerfwereade: Okay, but what's the failure about?16:19
fwereadeniemeyer, the failure is about whether a port gets closed in the environment or not16:20
niemeyerfwereade: Isn't that the bug we're discussing above?16:20
fwereadeniemeyer, not exactly -- the test doesn't exercise that precise situation16:21
fwereadeniemeyer, this is a port that should close but sometimes doesn't16:21
niemeyerfwereade: That's exactly the case we're talking about above16:21
fwereadeniemeyer, ...ok, they are more closely connected than I thought :/16:22
fwereadeniemeyer, I'd approached the conclusion from 2 separate directions, didn't realise they were the same place16:23
fwereadeniemeyer, so16:23
fwereadeniemeyer, I am comfortable that this is the bug16:23
fwereadeniemeyer, I have a patch for the test, to cause it to avoid exercising the bug16:24
fwereadeniemeyer, I am not *really* comfortable taking on "fix the firewaller" at this point, especially because I don't feel I know it as well as others16:24
niemeyerfwereade: I suspect the issue is simple to solve16:25
niemeyerfwereade: and to describe16:25
fwereadeniemeyer, yeah, it may be16:26
niemeyerfwereade: machined.ports starts empty16:26
niemeyerfwereade: That's it really16:26
fwereadeniemeyer, I'm a bit suspicious of unitd.ports starting empty too16:27
niemeyerfwereade: All the deltas are potentially wrong because of that16:27
fwereadeniemeyer, yeah, that does sound simpler to deal with16:28
niemeyerfwereade: I don't think that's a problem16:28
niemeyerfwereade: unitd.ports reflects what we learned from the state itself16:28
niemeyerfwereade: Which is always right16:28
fwereadeniemeyer, hold on, where does machined.ports come from if not from unitds' ports?16:28
fwereadeniemeyer, nah, it starts out empty16:28
niemeyerfwereade: Exactly16:28
niemeyerfwereade: We compute what we want machined.ports to be out of unitd.ports, which we learn from the state16:29
fwereadeniemeyer, ok, but16:29
fwereadeniemeyer, when a machine has >1 unit16:29
niemeyerfwereade: and diff against the previous value of machined.ports to know what to apply to the env16:29
fwereadeniemeyer, we cannot calculate the machined's ports without knowing all its unitds' ports, right?16:30
niemeyerfwereade: We know all unitd ports.. that's why we cache it16:31
fwereadeniemeyer, but we don't actually set it when we create it16:31
fwereadeniemeyer, it sits around empty until the main loop first handles a ports event for that unit16:31
niemeyerfwereade: Ah, interesting16:32
niemeyerme looks16:32
fwereadeniemeyer, so when a machine has 2 units, and we flush the machine's ports based on the first unit's ports only (because we haven't yet handled the second one's initial event) we have a problem16:32
fwereadeniemeyer, if I promise I will take a deeper look at it, can I patch the proximate problem by tweaking the test to skirt the problem?16:34
niemeyerfwereade: You can do that either way16:34
niemeyerfwereade: The problem is there and isn't going away until someone fixes it16:34
niemeyerfwereade: Your branch is orthogonal16:34
fwereadeniemeyer, true, but we don't want test failures dirtying up our lives16:35
fwereadeniemeyer, it was this bug, I think, that originally blocked it16:36
fwereadeniemeyer, ok, let me put it differently16:36
niemeyerfwereade: Yes, but the point of blocking is that no one could tell what the bug actually was16:36
fwereadeniemeyer, ah! and we now have progress?16:36
niemeyerfwereade: So whether it was orthogonal or not was at stake16:36
fwereadeniemeyer, that makes sense16:36
fwereadeniemeyer, got you16:36
niemeyerTheMue: Are you following?16:37
TheMueniemeyer: Yes, the whole time.16:37
niemeyerTheMue: Awesome, thanks16:37
niemeyerTheMue: Can we have a fix for the two issues next week?16:37
TheMueniemeyer: I think so, as it's now clearer.16:38
fwereadeniemeyer, TheMue: well, awesome :)16:38
niemeyerTheMue: Two different branches: 1) machined.ports must be properly initialized; that must be done differently for the two modes16:39
niemeyerTheMue: 2) Creating new machined's must ensure all unitd's within it are initialized before returning to the main loop16:39
niemeyerfwereade: Makes sense? Anything to add?16:39
fwereadeniemeyer, I think that covers it16:40
niemeyerTheMue: Questions?16:41
* TheMue feels comfortable with it too.16:41
fwereadeniemeyer, I will propose a trivial .Skip on that test for now16:42
fwereadeniemeyer, I think it's more valuable to have it preserved in a state that more-or-less exposes the issues than it is to hide them away by dodging the problem16:42
niemeyerfwereade: +116:42
* rogpeppe2 needs to do some navigation now. i may not return today. if not, have a great weekend everyone!16:48
TheMuerogpeppe2: Enjoy your weekend16:51
rogpeppe2TheMue: thanks. lots of obscure carols being sung this weekend - we're going to a Festival of Village Carols...16:52
* TheMue will step out in a few moments too. Tomorrow our little Vanessa has her next archery tournament. I'm excited.16:52
TheMuerogpeppe2: That's pre-christmas time … :D16:53
rogpeppe2TheMue: it's the 1st tomorrow!16:53
rogpeppe2TheMue: just scrapes into advent16:53
fwereadeniemeyer, https://codereview.appspot.com/684912616:53
fwereadeniemeyer, for form's sake :)16:53
TheMuerogpeppe2: Yep, have been to our local Christmas market yesterday. Has been quite good.16:54
niemeyerrogpeppe2: Have fun there17:00
niemeyerfwereade: +117:00
TheMueSo, I'm stepping out. Have a nice weekend everyone.17:43

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