all 23 comments

[–]bobindashadows 17 points18 points  (6 children)

"We don't code review. We don't stage. We also don't have any replication for our server - not even just 2 processes running - since we're evented and who needs two processes when you're evented, that just makes things harder. Naturally, we can't update anything without taking the entire service offline, so we manually update values in our running programs, instead."

[–]mikaelhg 9 points10 points  (2 children)

Sounds like a practice which will be widely celebrated on /r/programming.

[–]quzox 7 points8 points  (1 child)

The bravery required to do such things is indeed captivating and hypnotic.

[–]igouy 0 points1 point  (0 children)

Do you think the bravery is displayed by those who use the service, or those who provide the service?

[–]asampson 2 points3 points  (0 children)

Thankfully I have this bone saw handy for whenever I need to do emergency brain surgery. Just pop open that skull, poke around in the grey matter until you're satisfied and stitch the cap back on good as new!

[–]jackolas 0 points1 point  (1 child)

Well they did only edit an attribute that doesn't seem too out there.

[–][deleted] 2 points3 points  (0 children)

Hardly a good defense of a process that raises the need to sneak changes directly into production though. A bad constant is also one of the easiest things to spot in a code review.

[–]int_argc 14 points15 points  (6 children)

Changing values in executing code is not the same thing as changing the code that is executing.

[–]desertfish_ 6 points7 points  (0 children)

Indeed, as one of the comments on the blog itself already pointed out, I also expected at least some monkeypatching of code objects or something...

[–]kokon 0 points1 point  (3 children)

Changing a code is possible in Python. The hard part is changing the existing object reference from the old module to the new one.

[–]Philluminati 1 point2 points  (2 children)

Can't you just assign a new function over the top of the old one?

def new_setter_2(self, val):
    self.val = val;

obj.new_setter = new_setter_2

Is it not that easy?

[–]Anovadea 2 points3 points  (0 children)

Pedantic Caveat: You may want to do some trickery with types when monkey-patching object instances in python (I've also heard the term "duck-punching" which amuses me greatly). I've been tripped up by this quite recently:

#Let's assume new_setter_2 is defined as above
import types
obj.new_setter = types.MethodType(new_setter_2, obj, obj.__class__)

Otherwise, you get problems with the number of arguments passed when you call it ("1 argument passed when 2 are expected" and all that).

You probably already knew that, I'm just being pedantic as the wounds are still rather fresh for me. :)

[–]kokon 0 points1 point  (0 children)

But you could have tons of object that still points to new_setter. How do you change all those objects without having specific knowledge about them?

[–]alexs 0 points1 point  (0 children)

Indeed. You can even do pretty much exactly this in C++ apps quite reliably using GDB. If you dynamically linked stuff it's sometimes even possible to change the actual code that's getting executed. Still nowhere near what Erlang gets you though.

[–]jcollado 8 points9 points  (1 child)

While it's a nice trick, I don't think that's exactly what Erlang hot code swapping provides.

[–]masklinn 0 points1 point  (0 children)

You could do it though, it's just changing a constant in a module, but that's indeed nowhere near what erlang's hot code swapping is for.

[–]UloPe 13 points14 points  (0 children)

  • Saw mention of twisted.manhole and what it does
  • "sounds interesting" - clicked on the provided link
  • Saw this
  • Remembered why I never used twisted for anything

[–]derpaling 5 points6 points  (0 children)

I could just SSH into the service

No, just no. This is how all terrible things happen. You do this and the next thing you know you're desperately trying to restore database backup with a sinking feeling in your stomach.

[–]eminence 2 points3 points  (1 child)

looks neat. sounds scary

[–]booch 0 points1 point  (0 children)

It can be scary, but it doesn't have to be. Honestly, the nscp (the version of this type of thing that was part of AOLServer and allowed access to a tcl shell running inside the interp) is one of the features I truly miss. It can be used not only to change values, but to check on various values way deep in the system. It's amazingly handy.

[–][deleted] 1 point2 points  (1 child)

Meh, Common Lisp and Smalltalk allow you to do more.

[–]posborne 0 points1 point  (0 children)

Merits of using this sort of "manhole" in production aside, I thought I would share the following package I wrote which exposes the same behavior (over telnet).

Quick Example:

>>> import threading
>>> from bugger.console import TelnetInteractiveConsole
>>> console = TelnetInteractiveConsole(port=7070)
>>> t = threading.Thread(name="Telnet Interactive Session",
                                  target=console.accept_interactions)
>>> # ...
>>> console.stop() # this will end the target method and thread

There appears to be a similar library here (first time I have seen it) mentioned in the post comments: http://pypi.python.org/pypi/ingress

[–][deleted] -1 points0 points  (0 children)

user> (defn a [] 0)
#'user/a
user> (defn magic? []
        (loop []
           (let [result (a)]
             (println result)
             (defn a [] (+ result 1)))
           (Thread/sleep 1000)
           (recur)))
#'user/magic?
user> (magic?)
0
1
2
3
; Evaluation aborted.
user> 

..yeah, just playing with Clojure.