delay package and gob encoding issue

77 views
Skip to first unread message

Christopher Hesse

unread,
Nov 19, 2014, 7:43:09 PM11/19/14
to google-ap...@googlegroups.com
Hi!  I'm using delay and getting an odd issue that happens only sometimes, the error message looks like this:

delay: failed decoding task payload: gob: name not registered for interface: "main68172.Object"

My theory is that gob is encoding my object (I think it should be hello.Object) as main68172.Object.  This is problematic when tasks pass between different versions of the same module, but also (as I discovered today) even when they don't leave the module.  I am assuming that there are different versions of my app being compiled behind the scenes or something like that.

Here is an example of the behavior:


I can see "main61029.Object" in the payload, which is very suspicious to me.  One workaround is to put the struct inside of a different package from everything else, this seems to use the package name correctly judging from the payload string.

Does anyone know why this is happening? Is there a better workaround than putting things into other modules?

Derek Perkins

unread,
Nov 19, 2014, 8:39:33 PM11/19/14
to google-ap...@googlegroups.com
From David Symonds: "You must assign the delay.Func result to a global var at init time. The package docs say this"

There's extra detail in this thread.

David Symonds

unread,
Nov 19, 2014, 8:42:51 PM11/19/14
to Christopher Hesse, google-appengine-go
If you're storing a concrete type in an interface value then you need
to gob.Register that type. The appengine/delay package calls this out,
and links to http://golang.org/pkg/gob/#Register.

Christopher Hesse

unread,
Nov 19, 2014, 9:12:32 PM11/19/14
to google-ap...@googlegroups.com, ch...@pushbullet.com
@Derek:  I think I am doing that already.  I looked at that thread but it did not seem to be the same issue as this one.

@David Symonds:  Thanks for the quick response!  I read that part of the delay docs, but since my example does not use any interface{} types in the function definition, I thought it did not apply to me.  I tried calling gob.Register(Object{}) in init, but the serialized gob data still seems to contain " main63451.Object".  Attempting to call gob.RegisterName("hello.Object", Object{}) as the name produces an error (delay seems to register the type before I do).  Could you give me a more concrete example to show what I'm doing wrong here? 

David Symonds

unread,
Nov 19, 2014, 9:37:09 PM11/19/14
to Christopher Hesse, google-appengine-go
You are writing
args := []interface{}{Object{}}
or is that just experimentation?

It shouldn't matter what actually appears in the encoded gob; if the
code is consistent then it'll decode. Can you post another gist
showing your gob.Register(Object{})?

There's a functional sample app in demos/delay (inside the SDK) that
shows how this should work, but your code is close enough to that that
it should be working.


I *would* expect there to be issues passing an encoded gob (and thus a
delayed func) between different app versions. That often won't work.
It should be fine when called within the same module, though it can
sometimes be confusing which module ends up executing the task. Try
logging appengine.ModuleHostname(c, "", "", "") to be sure.

Christopher Hesse

unread,
Nov 19, 2014, 10:05:25 PM11/19/14
to google-ap...@googlegroups.com, ch...@pushbullet.com
Yeah sorry about that, that line was there just to compare the output, I should have removed it from the example.  The behavior I get from running go locally seems fine, it's when it's on appengine that I see this "main63451.Object" stuff.


To clarify: the code in my original example works, at least as long as you don't deploy a new version while tasks are enqueued. Like you said, this shouldn't be a problem when sending between the same versions of the same module, but I believe I observed that today.  One theory would be that, for instance, if for some reason the binary was recompiled for the same version, instead of "main63451" it might be "main01727" and then the tasks would fail because gob decoding would not work.

It looks like this particular issue can be resolved by moving Object{} into a different module, like submodule.Object{}.  The name then appears to be stored correctly.  
Another possible workaround, like you suggested, might be to do RegisterName() before delay does it, and then specify a name like "hello.Object".   I'm not sure how to do that if delay attempts to re-register the type with the default name though.

David Symonds

unread,
Nov 19, 2014, 10:12:57 PM11/19/14
to Christopher Hesse, google-appengine-go
On 20 November 2014 14:05, Christopher Hesse <ch...@pushbullet.com> wrote:

> It looks like this particular issue can be resolved by moving Object{} into
> a different module, like submodule.Object{}. The name then appears to be
> stored correctly.

Yes, that's probably the most stable solution. Gob seems to depend on
a stable package name, but the top-level app package does not get one.

Christopher Hesse

unread,
Nov 19, 2014, 10:18:44 PM11/19/14
to google-ap...@googlegroups.com, ch...@pushbullet.com
Thanks for the help!  I have my own fork of delay, so I may just remove the gob.Register() part from there and do it manually with RegisterName().

Reply all
Reply to author
Forward
0 new messages