Comms in monkey.barrels?

I'm experimenting with monkey.barrels and getting an error when accessing Communications.

using Toybox.Communications as Comms;
...
Comms.makeWebRequest(
url,
params,
{ :headers => headers,
:method =>Comms.HTTP_REQUEST_METHOD_POST,
:responseType => Comms.HTTP_RESPONSE_CONTENT_TYPE_JSON
},
method(:sendLogsCallback)
) ;


Code obviously works fine in original build, but when I put it in barrels it fails at runtime with
Symbol Not Found Error
in sendLogs (/private/var/folders/ly/qnh242bx7z98fz51w0yvjvjm0000gn/T/sharedCode-0.0.0.barrel13810905824211180534/content/sharedCode.mc:123)

Line 123 is Comms.makeWebRequest.
Is there a limitation I'm missing?

  • Need more info, as I have a barrel that not only does comm, but runs as a background process. What permissions do you have on the main app? You'll need comm there and not just in the barrel.
  • Ah, yes, overlooked permissions, thanks.
    (why doesn't it report a permissions error????)
  • Hmmm. I fixed permissions in barrels project's manifest file :<iq:permissions>
    <iq:uses-permission id="Communications"/>
    </iq:permissions>

    Exported the barrels file, but still get the symbol not found error on the same line.
    Maybe a deeper issue?


  • I think the problem lies here, with method(:sendLogsCallback):
    function sendLogsCallback(responseCode, data){
    if (responseCode>=200){
    System.println(" sendLogsCallback data:\n " + data);
    }
    }
    ....
    function sendLogs(
    .......

    Comm.makeWebRequest(
    url,
    params,
    {
    :method =>Comm.HTTP_REQUEST_METHOD_POST,
    :responseType => Comm.HTTP_RESPONSE_CONTENT_TYPE_JSON
    }
    ,method(:sendLogsCallback)
    ) ;

    I've never understood this syntax, but it has worked up to now.
    I don't think it's finding :sendLogsCallback.
    When I tweaked the original code, I could induce exactly the same error by omitting the sendLogsCallback() function.
  • [UPDATE]My error is now: "Could not find symbol method."

    Could not find symbol method.
    Symbol Not Found Error
    in sendLogs (/private/var/folders/ly/qnh242bx7z98fz51w0yvjvjm0000gn/T/sharedCode-0.0.0.barrel2908580989542756205/content/sharedCode.mc:109)
  • It sounds like maybe your original problem was permissions.. I believe you need to set the permission on the barrel and the application to have access to features that require permissions.

    Given the current error message, it seems that sendLogsCallback is defined at global or a module scope. If so, that is the problem. The function named method() is a member of Lang.Object which all objects of class type inherit from (implicitly). So if you are writing code inside a class definition, you will have access to the method() function. If you are at module scope (the global scope is just a special module with the name $), you don't have that function available to call.

    The solution is to either
    • Use a class. In most cases this makes sense, but there are cases where it doesn't.
    • Instantiate a Lang.Method instance to do what you need (something like new Lang.Method($, :sendLogsCallback))
  • It sounds like maybe your original problem was permissions.. I believe you need to set the permission on the barrel and the application to have access to features that require permissions.

    Thanks for your response.
    Unfortunately the forum refuses to accept my response which it happily previews but fails to post with a JSON error.

    So I'm still in the dark.



  • In my efforts to overcome the memory limitations of the platform and pack more features into my app, I am exploring the option of re-architecting the app from a single app to a pair of apps, using exitTo() to navigate between them. Usability-wise, this is acceptable as the use case does have two logical components: Starting and Racing.

    In splitting the app, I find that there is much code is common to both components, so I have spent the past week exploring monkey.barrels to handle the problem.

    My conclusion is that, for this purpose, it is no help.

    Here are my conclusions:
    • Having to provide permissions and devices to the barrel project when they have already been applied to the parent project just seems like sloppy engineering.
    • Negotiating the obscurities of global and module scopes to implement comms turned out to be beyond the capability of this developer.
    • There is a significant memory overhead just in using barrels which countervails against my primary objective of recovering memory.
      Moving a single function from the parent project to a barrel (if that's the correct terminology) increased the Peak Memory usage of may app in the Sim by 5.5 Kb, from 113.5 kB to 119 kB.
    • But the nail in the coffin is that there appears to be a memory leak in the barrels implementation. When I run my app in the Sim with the barrels configuration (above) it crashes out of memory after a running for a couple of minutes. I'm monitoring the memory usage and Peak Memory, and they both increase steadily during the run until memory Peak Memory approaches 121Kb just before it crashes.
      When I run the app in the original configuration, it runs indefinitely, with the Peak Memory steady at 113.5 Kb.
  • One thing with barrels (I have about a dozen right now) is that I write them in such a way that they can be used as a barrel, or I can just use a link from the main project to the source/resources in the barrel project. I've been using links in eclipse, but with those, you can't use jungles. I think OS level links would avoid this problem, but not tried. I have seen an overhead for using a barrell vs linked code, but not as much as you.

    End result, is for a specific function, I have a single .mc for a function, whether it's linked as source to a project, or used in a barrel for a project

    Permissions on the barrel as well as the main app is kind of handy. If a barrel has a permission set, and you add it to a new project, you'll get an error/warning if the main app doesn't have that permission. (which is where it really matters).

    I've not seen a case where barrels have caused a memory leak, and I've used them in a number of projects, with a number of SDKs. Are you doing something were you create multiple instances of the class(es) you have in the barrel? Maybe try just using a link instead of a barrell and see if you have the same result.
  • Could you expand on the implementation of links?
    With a single .mc for a function (as I have done) how do you structure the code? as a class, module or what? Could you offer a simple example?
    Re the memory leak, no, I don't think I'm creating multiple classes. In my barrel, I have a single class "class sharedCode{" , containing a single function "function sendLogs(...){ " which I'm invoking from may main project every 60 seconds with "sharedCode.sendLogs(...);" (Where ... is a list of arguments.) I can't see how that would cause multiple classes to be created?
    I used a similar structure using module instead of class with the same results.
    [EDIT]
    In case you'r wondering, sendLogs() only sends the previous 60 second's data, so each call sends about the same amount of data.