Amber Smalltalk on AWS Lambda

154 views
Skip to first unread message

Herby Vojčík

unread,
May 28, 2019, 4:43:31 PM5/28/19
to Amber ML
Ok, so ...

a few days ago Stefan Krecher asked how to run Amber on AWS Lambda. So I
looked at it, and - there is the backend part now by default in the
initial project.

So update your amber:

npm -g install @ambers/cli

and if `npm ls -g @ambers/grunt-init-amber-project` does not show at
least version 0.23.5, then force npm:

npm -g uninstall @ambers/cli -f
npm cache clean -f
npm -g install @ambers/cli -f

and you should have the new project scaffolding installed. Run your
beloved `amber init` in an empty directory, and after you run `amber
serve` and start Helios, you see your project has new
YourProject-Backend package with YourProjectBackend class.

Your project also has `lambda` directory with `index.js` file. This just
defines instance of which class should be used to serve the requests and
defines handler(s) by specifying which selector to use. The rest is
magic in Gruntfile.js which now allows to pack the backend Amber package
and its dependencies. In a parallel terminal (so your `amber serve`
still runs), run

grunt deploy:lambda

and the lambda/the.js is built. This file is needed by lambda/index.js
and it includes everything that the backend package(s), as specified in
lambda.js (backend analogy of deploy.js), need. Now you just zip the
contents of the lambda directory, and you have the deployment package
that you can use in AWS Lambda.

The code in initial app has the button that actually calls your Lambda
function and shows you the result. It supposes that you create AWS API
Gateway using proxy integration (the defaults if you use Lambda the
first time), and that your endpoints (and functions) are called `echo`
and `status` (obviously, those are the exported handler names in index.js).

Go to your Helios IDE, find YourProject >> endpoint, and specify path to
the API Gateway. From that point on, the "Inspect status of backend"
should call your Lambda function and open the result in Helios' inspect
pane (or show you the dialog with an error).

Use Amber on both frontend and backend and be happy,

Herby

P.S.: The cold start takes some time, around 500ms (the single Amber
hierarchy is not a true single hierarchy - there are detached JS classes
like Number, Array, Date, String, Function for which full set of DNU
handlers and copied methods from logical Amber superclass must be
installed to give the impression of single Smalltalk hierarchy, and that
takes time and is done eagerly during startup... I can see into it if
can be lazified), but the subsequent ones sharing execution context are
fast.

Stefan Krecher

unread,
Jul 5, 2019, 9:33:26 AM7/5/19
to amber...@googlegroups.com
Hi,
I did this:
npm -g uninstall @ambers/cli -f
npm cache clean -f
npm -g install @ambers/cli -f

npm ls -g @ambers/grunt-init-amber-project shows:
`-- @ambers/c...@0.105.0
  `-- @ambers/grunt-init-a...@0.24.0

"amber version" shows this:
Welcome to Amber CLI version 0.105.0 (Amber 0.23.0-pre, NodeJS 10.15.0).

But when I create a scaffold with "amber init", I don't see the *-Backend package and there was no "lambda" directory created.

What did I do wrong?

Thanks 
Stefan


--
You received this message because you are subscribed to the Google Groups "amber-lang" group.
To unsubscribe from this group and stop receiving emails from it, send an email to amber-lang+...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/amber-lang/ad572ba6-000a-df67-85f4-04ef08557c58%40mailbox.sk.
For more options, visit https://groups.google.com/d/optout.

Herby Vojčík

unread,
Jul 5, 2019, 9:55:05 AM7/5/19
to amber...@googlegroups.com, Stefan Krecher


Dňa 5. júla 2019 15:33:12 SELČ používateľ Stefan Krecher <stefan....@gmail.com> napísal:
>Hi,
>I did this:
>npm -g uninstall @ambers/cli -f
>npm cache clean -f
>npm -g install @ambers/cli -f
>
>npm ls -g @ambers/grunt-init-amber-project shows:
>`-- @ambers/c...@0.105.0
> `-- @ambers/grunt-init-a...@0.24.0
>
>"amber version" shows this:
>Welcome to Amber CLI version 0.105.0 (Amber 0.23.0-pre, NodeJS
>10.15.0).
>
>But when I create a scaffold with "amber init", I don't see the
>*-Backend
>package and there was no "lambda" directory created.
>
>What did I do wrong?

I don't know. It is strange, that should definitely not be the case. :-/ 0.24.0 is good template. "amber" cli seems to be running the correct npm-installed thing. :-( (try uninstall and run "amber init" anyway if there isn't some dangling old installation in your setup). Or zoom me or skype me at drudkin.

Herby

Stefan Krecher

unread,
Jul 8, 2019, 6:09:03 PM7/8/19
to amber...@googlegroups.com
While playing around with the backend-feature, the next step would be to import the AWS-SDK Javascript library.
I installed it with npm install aws-sdk and flipped through all the documentation regarding the use of 3rd-party libraries with amber.
The aws-sdk does not seem to include an "amd" file (I have no idea what that would be for), so I added this to the config.js file:
"aws": 'node_modules/aws-sdk/dist/aws-sdk.js',
and
'aws': {
      'exports': 'AWS'
    },
in the "shim" section.
This didn't seem to work - I wanted to make some AWS API calls from a workspace.
Can you point me in the right direction?
Thanks in advance
Stefan

Am Sa., 6. Juli 2019 um 13:48 Uhr schrieb Stefan Krecher <stefan....@gmail.com>:
Hey - I finally made it. Looks like I had messed up multiple versions of the cli on my computer.
Sorry to bother you


--
Dipl.-Wirtsch.-Inf. Stefan Krecher
Neulander Str. 17, 27374 Visselhövede
Tel +49(0)4262 958848
mobil +49(0)172 4396852

Herby Vojčík

unread,
Jul 8, 2019, 6:23:16 PM7/8/19
to amber...@googlegroups.com, Stefan Krecher
You don't edit config.js (it's mentioned in it's beginning).

You create dirname.amd.json file for 3rd library and assemble config.js by amdconfig task (run as part of amber devel, for example).

Will post details later, writing from my phone.

Herby

Dňa 9. júla 2019 0:08:49 SELČ používateľ Stefan Krecher <stefan....@gmail.com> napísal:

Herby Vojčík

unread,
Jul 9, 2019, 6:16:47 AM7/9/19
to amber...@googlegroups.com, Stefan Krecher
On 9. 7. 2019 0:23, Herby Voj????k wrote:
> You don't edit config.js (it's mentioned in it's beginning).
>
> You create dirname.amd.json file for 3rd library and assemble config.js
> by amdconfig task (run as part of amber devel, for example).
>
> Will post details later, writing from my phone.
>
> Herby

Have you read this
https://github.com/amber-smalltalk/amber/wiki/Building-blocks-of-Amber-application-(and-library)?
Just replace bower with npm (bower is not used any more) and it should
be correct.

As for AWS SDK, it seems it is not packed in UMD form, so AMD loader can
not load it, but exports should work fine.

It is just that you need to create aws.amd.json or aws-sdk.amd.json (I
don't know what will be the name of the directory where it installs
into) with proper paths section relative to that dir and shim sections
(exports should work).

If you would like to load it in workspace, you would need to use require
directly, which I want to deprecate in favour of general package loader
based off JS dynamic import.

So I would advise to add aws in imports: of your app package (or
background package), as in

imports: {" ...others... ". 'aws' -> 'AWS'}

(I presume you want to use it anyway) then add some class-level method
in some class to expose it

MyClass >> publishedAws
^ aws

and in workspace just use MyClass publishedAws (inside the package with
import, you can just use 'aws' variable directly; imports: defines
'package-level' variables in reality).

Herby

> D??a 9. j??la 2019 0:08:49 SEL?? pou????vate?? Stefan Krecher
> <stefan....@gmail.com> nap??sal:
>
> While playing around with the backend-feature, the next step would
> be to import the AWS-SDK Javascript library.
> I installed it with npm install aws-sdk and flipped through all the
> documentation regarding the use of 3rd-party libraries with amber.
> The aws-sdk does not seem to include an "amd" file (I have no idea
> what that would be for), so I added this to the config.js file:
> "aws": 'node_modules/aws-sdk/dist/aws-sdk.js',
> and
> 'aws': {
> ?? ?? ?? 'exports': 'AWS'
> ?? ?? },
> in the "shim" section.
> This didn't seem to work - I wanted to make some AWS API calls from
> a workspace.
> Can you point me??in the right direction?
> Thanks in advance
> Stefan
>
> Am Sa., 6. Juli 2019 um 13:48??Uhr schrieb Stefan Krecher
> <stefan....@gmail.com <mailto:stefan....@gmail.com>>:
>
> Hey - I finally made it. Looks like I had messed up multiple
> versions of the cli on my computer.
> Sorry to bother you
>
> Am Fr., 5. Juli 2019 um 15:55??Uhr schrieb Herby Voj????k
> <he...@mailbox.sk <mailto:he...@mailbox.sk>>:
>
>
>
> D??a 5. j??la 2019 15:33:12 SEL?? pou????vate?? Stefan Krecher
> <stefan....@gmail.com <mailto:stefan....@gmail.com>>
> nap??sal:
> >Hi,
> >I did this:
> >npm -g uninstall @ambers/cli -f
> >npm cache clean -f
> >npm -g install @ambers/cli -f
> >
> >npm ls -g @ambers/grunt-init-amber-project shows:
> >`-- @ambers/c...@0.105.0
> >?? `-- @ambers/grunt-init-a...@0.24.0
> >
> >"amber version" shows this:
> >Welcome to Amber CLI version 0.105.0 (Amber 0.23.0-pre, NodeJS
> >10.15.0).
> >
> >But when I create a scaffold with "amber init", I don't
> see the
> >*-Backend
> >package and there was no "lambda" directory created.
> >
> >What did I do wrong?
>
> I don't know. It is strange, that should definitely not be
> the case. :-/ 0.24.0 is good template. "amber" cli seems to
> be running the correct npm-installed thing. :-( (try
> uninstall and run "amber init" anyway if there isn't some
> dangling old installation in your setup). Or zoom me or
> skype me at drudkin.
>
> Herby
>
> >Thanks
> >Stefan
> >
> >
> >Am Di., 28. Mai 2019 um 22:43 Uhr schrieb Herby Voj????k
> ><he...@mailbox.sk <mailto:he...@mailbox.sk>>:
> >
> >> Ok, so ...
> >>
> >> a few days ago Stefan Krecher asked how to run Amber on
> AWS Lambda.
> >So I
> >> looked at it, and - there is the backend part now by
> default in the
> >> initial project.
> >>
> >> So update your amber:
> >>
> >>?? ?? npm -g install @ambers/cli
> >>
> >> and if `npm ls -g @ambers/grunt-init-amber-project` does
> not show at
> >> least version 0.23.5, then force npm:
> >>
> >>?? ?? npm -g uninstall @ambers/cli -f
> >>?? ?? npm cache clean -f
> >>?? ?? npm -g install @ambers/cli -f
> >>
> >> and you should have the new project scaffolding
> installed. Run your
> >> beloved `amber init` in an empty directory, and after
> you run `amber
> >> serve` and start Helios, you see your project has new
> >> YourProject-Backend package with YourProjectBackend class.
> >>
> >> Your project also has `lambda` directory with `index.js`
> file. This
> >just
> >> defines instance of which class should be used to serve
> the requests
> >and
> >> defines handler(s) by specifying which selector to use.
> The rest is
> >> magic in Gruntfile.js which now allows to pack the
> backend Amber
> >package
> >> and its dependencies. In a parallel terminal (so your
> `amber serve`
> >> still runs), run
> >>
> >>?? ?? grunt deploy:lambda
> <mailto:amber-lang%2Bunsu...@googlegroups.com>.
> >> To view this discussion on the web visit
> >>
> >https://groups.google.com/d/msgid/amber-lang/ad572ba6-000a-df67-85f4-04ef08557c58%40mailbox.sk
> >> .
> >> For more options, visit https://groups.google.com/d/optout.
>
>
>
>
> --
> Dipl.-Wirtsch.-Inf. Stefan Krecher
> Neulander Str. 17, 27374 Visselh??vede
> --
> You received this message because you are subscribed to the Google
> Groups "amber-lang" group.
> To unsubscribe from this group and stop receiving emails from it, send
> an email to amber-lang+...@googlegroups.com
> <mailto:amber-lang+...@googlegroups.com>.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/amber-lang/7D573430-A28C-4744-AA86-DE0F3C58FC48%40mailbox.sk
> <https://groups.google.com/d/msgid/amber-lang/7D573430-A28C-4744-AA86-DE0F3C58FC48%40mailbox.sk?utm_medium=email&utm_source=footer>.

Stefan Krecher

unread,
Jul 9, 2019, 1:02:37 PM7/9/19
to amber...@googlegroups.com
Hey Herby,
thanks for taking the time - but it doesn't work for me ...
A couple of years ago it was much easier to include a JS library in amber - now there are so many config-files/ tools involved ...
I created an aws-sdk.amd.json file with this content:
{
    "paths": {
        "aws-sdk": "dist"
    }
}
and generated the config.js file via "grunt devel".
In config.js I see the line
"aws-sdk": "node_modules/aws-sdk/dist",
And I assume that everything in that file should be available in amber - but this doesn't seem to be the case.

I created a shim-section in the aws-sdk.amd.json file:
"aws-sdk": {
      "exports": "AWS"
}
But this didn't help either - using the developer-mode in chrome, I couldn't find the aws-sdk and importing AWS/ aws in the package-section didn't help.

Is the "old" way of using a library still possible? If I remember correctly, I just had to include the library on the html-page with <script src=.../> and the initialize the library inside a "<" and a ">"

Regards
Stefan

Herby Vojčík

unread,
Jul 9, 2019, 1:43:53 PM7/9/19
to amber...@googlegroups.com, Stefan Krecher
On 9. 7. 2019 19:02, Stefan Krecher wrote:
> Hey Herby,
> I created an aws-sdk.amd.json file with this content:
> {
> ?? ?? "paths": {
> ?? ?? ?? ?? "aws-sdk": "dist"
> ?? ?? }
> }
> and generated the config.js file via "grunt devel".
> In config.js I see the line
> "aws-sdk": "node_modules/aws-sdk/dist",

Seems like path mapping to me. Is this what you want (and then load
modules like 'aws-sdk/global' or similar?

One note: the fields does not need mimic the directory, it's the key you
choose, so it may as well be "aws": "dist".

If you just want to map one file, map it directly, so you can then just
load the specific .js file by the simple name.

> And I assume that everything in that file should be available in amber -
> but this doesn't seem to be the case.

Again, is it a file (dist.js)? If yes, then ok. If not, what do you
expect to load automatically?

Anyway, it is available for the _loader_ as the name -> folder / file
mapping (that's what config.js is, complete configuration of the loader,
and nothing more).

So, basically, you can do (if it is indeed mapped to a file) `require
value: #('aws-sdk') value: [ :aws | ... ]` and get the answer (two buts:
first, as I already wrote, doing it this way should be treated as
deprecated as it uses one type of loader's protocol specifically and
second, it won't work anyway, it needs the exports: clause you mentioned
below).

Any JS library must be loaded somewhere to be accessible. The best way
to do it in modern (that is, a few years already) Amber is to use
package's imports: line. That is how it is done all over Amber nowadays
(jquery wrapper does that, Helios does that with its dependencies etc.).
You instruct package that this is a dependency you need loaded before
its code runs and the system loads it for you (and if you specify it in
association style, also created package-level variable that stores the
export of that library), whatever the loader is now or will be later (at
least I'd like this to be the case).

> I created a shim-section in the aws-sdk.amd.json file:
> "aws-sdk": {
> ?? ?? ?? "exports": "AWS"
> }

Yes, that's needed as well, so that it knows the export value.

> But this didn't help either - using the developer-mode in chrome, I
> couldn't find the aws-sdk and importing AWS/ aws in the package-section

OF course, 'AWS' is not mapped to anything. You specified 'aws-sdk' name
in you .amd.json. You define the name for the module id by choosing what
you put in paths: section. Importing 'aws-sdk/aws' could work in this
case (but again, if you only need to use this file, probably map it
directly in paths as "aws": "dist/aws" and import: 'aws'->'aws').

> didn't help.

Because the lib needs to be loaded. The fact that it is in config.js
only allows for loading, but does not do the loading.

> Is the "old" way of using a library still possible? If I remember
> correctly, I just had to include the library on the html-page with
> <script src=.../> and the initialize the library inside a "<" and a ">"

Not recommended.

Remember that you want it as a dependency. For example if your backend
code is to use it. It is compiled to node, there is no <script> there.
Also, the deploy story would be complicated, `grunt deploy` would not
include it if you loaded it just in index.html directly, but it will be
if you specify it as dependency of one .js module on another (which is
what imports: compiles to, in a way).

> Regards
> Stefan
>
> Am Di., 9. Juli 2019 um 12:16??Uhr schrieb Herby Voj????k <he...@mailbox.sk
> <mailto:he...@mailbox.sk>>:
> ?? ??^ aws
>
> and in workspace just use MyClass publishedAws (inside the package with
> import, you can just use 'aws' variable directly; imports: defines
> 'package-level' variables in reality).
>
> Herby
>
> --
> You received this message because you are subscribed to the Google
> Groups "amber-lang" group.
> To unsubscribe from this group and stop receiving emails from it, send
> an email to amber-lang+...@googlegroups.com
> <mailto:amber-lang+...@googlegroups.com>.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/amber-lang/CADB_sZxPiA9f5Bj89-Y8ocg-Zcqv-o38ZwmJF0XvrzMDaM2D%3Dg%40mail.gmail.com
> <https://groups.google.com/d/msgid/amber-lang/CADB_sZxPiA9f5Bj89-Y8ocg-Zcqv-o38ZwmJF0XvrzMDaM2D%3Dg%40mail.gmail.com?utm_medium=email&utm_source=footer>.

Stefan Krecher

unread,
Jul 11, 2019, 6:54:12 AM7/11/19
to amber...@googlegroups.com
Hey Herby,
With your instructions I finally managed to load the aws-sdk :-)

I wanted to do a simple ec2 describe-instances call against the aws api. I've been using the Python SDK (boto3), but the node sdk seems to be different.
With Python I do the API call and then get the response back in JSON format.
With node it looks like I need to use a callback-function to handle the results.
This is an example call:

var params = { InstanceIds: [ "i-1234567890abcdef0" ] }; ec2.describeInstances(params, function(err, data) { if (err) console.log(err, err.stack); // an error occurred else console.log(data); // successful response /* data = { } */ });  

To do the same with amber, first I need to initialize the AWS class with my credentials:

| aDict |
aDict := Dictionary new.
aDict at: #accessKeyId put: 'myaccesskey'.
aDict at: #secretAccessKey put: 'mysecretaccesskey'.
aDict at: #region put: 'eu-central-1'.
AWS config update: aDict

This call:
AWS EC2 new describeInstances
returns an object with a lot of attributes, including a "response" object. Sadly the response-object doesn't include data (the value for "data" is nil) but it also does not include an error-message or anything useful.

If I try to pass arguments (an empty dictionary and a Block) to the describeInstances call like in the above example:
AWS EC2 new describeInstances: #((Dictionary new) [:i | Transcript show: i])
the return value when executing this is nil and nothing is printed in the Transcript.

While doing some research on this, I read that you call Amber a "Smalltalk for Javascripters". So what do you think - to which degree do I need to dive into Javascript/ node to make use of Amber in production-environments? And do you have any recommendation on how to learn the things that are needed to use Amber, so I don't need to bother you regarding each line of code?
I've been working with Java and Python for many years and of course with Smalltalk (but the last "real" Smalltalk-Project that I was involved was almost twenty years ago ...).
Regards
Stefan

Herby Vojčík

unread,
Jul 11, 2019, 7:11:49 AM7/11/19
to amber...@googlegroups.com, Stefan Krecher
On 11. 7. 2019 12:53, Stefan Krecher wrote:
> Hey Herby,
> With your instructions I finally managed to load the aws-sdk :-)
>
> I wanted to do a simple ec2 describe-instances call against the aws api.
> I've been using the Python SDK (boto3), but the node sdk seems to be
> different.
> With Python I do the API call and then get the response back in JSON format.
> With node it looks like I need to use a callback-function to handle the
> results.
> This is an example call:
>
> varparams = { InstanceIds: [ "i-1234567890abcdef0"] };
> ec2.describeInstances(params, function(err, data) { if(err)
> console.log(err, err.stack); // an error occurredelseconsole.log(data);
> // successful response/* data = { } */});
>
> To do the same with amber, first I need to initialize the AWS class with
> my credentials:
>
> | aDict |
> aDict := Dictionary new.
> aDict at: #accessKeyId put: 'myaccesskey'.
> aDict at: #secretAccessKey put: 'mysecretaccesskey'.
> aDict at: #region put: 'eu-central-1'.
> AWS config update: aDict

I would say this won't work. Dictionary is full-fledged Smalltalk
dictionary indexable by objects, which does not translate to JS
stringkey-objectvalue objects. For this, there is HashedCollection,
which has convenient syntax #{ assoc. assoc. ... } to create directly.
It is also an Amber class, but keys can only be strings and it encodes
the key-value mechanism the JS way.

Maybe you wanted:

AWS config update: #{
#accessKey -> 'myaccessKey'. "ok since symbols and strings"
#secretAccessKey -> 'mysecretaccesskey'. "are same in Amber"
#region -> 'eu-central-1' "so just use them for proper style"
}

> This call:
> AWS EC2 new describeInstances
> returns an object with a lot of attributes, including a "response"
> object. Sadly the response-object doesn't include data (the value for
> "data" is nil) but it also does not include an error-message or anything
> useful.
>
> If I try to pass arguments (an empty dictionary and a Block) to the
> describeInstances call like in the above example:
> AWS EC2 new describeInstances: #((Dictionary new) [:i | Transcript show: i])

External JS call

obj.fooBar(baz, quux)

is done as

obj fooBar: baz whateverHere: quux

Not to mention #() is literal array so if you looked at it in workspace,
you could get something like #(':' 'i' '|' 'Transcript' 'show:' 'i' ']')
as a result, { foo. bar. baz } is dynamic array, just as in Squeak and
Pharo.

So you wanted to

AWS EC2 new describeInstances: #{} thenDo: [:err :result | ...]

> the return value when executing this is nil and nothing is printed in
> the Transcript.
>
> While doing some research on this, I read that you call Amber a
> "Smalltalk for Javascripters". So what do you think - to which degree do
> I need to dive into Javascript/ node to make use of Amber in
> production-environments? And do you have any recommendation on how to

Hopefully not much. You should understand how JavaScript is working a
bit (so that #value: is actually #cull:, for example), and to be able to
understand Amber <-> JS mappings to not shoot yourself to the foot.

I think it won't be so bad, with "how to call external API" and "use
#{...} where JS object is presumed" you basically know enough to do most
things already.

> learn the things that are needed to use Amber, so I don't need to bother
> you regarding each line of code?
> I've been working with Java and Python for many years and of course with
> Smalltalk (but the last "real" Smalltalk-Project that I was involved was
> almost twenty years ago ...).
> Regards
> Stefan

Don't worry,

Herby

Herby Vojčík

unread,
Jul 11, 2019, 7:20:18 AM7/11/19
to amber...@googlegroups.com, Stefan Krecher
On 11. 7. 2019 12:53, Stefan Krecher wrote:
> Hey Herby,
> With your instructions I finally managed to load the aws-sdk :-)
>
> I wanted to do a simple ec2 describe-instances call against the aws api.
> I've been using the Python SDK (boto3), but the node sdk seems to be
> different.
> With Python I do the API call and then get the response back in JSON format.
> With node it looks like I need to use a callback-function to handle the
> results.
> This is an example call:
>
> varparams = { InstanceIds: [ "i-1234567890abcdef0"] };
> ec2.describeInstances(params, function(err, data) { if(err)
> console.log(err, err.stack); // an error occurredelseconsole.log(data);
> // successful response/* data = { } */});

Doesn't AWS SDK version with Promises? It is seen as more modern style
of doing async in JS (and as such will get more and more prevalent).

If it does have a version that permits you to just

ec2.describeInstances(params)
.then(function (data) {...success...})
.catch(function (err) { console.error(err); });

then you can do it in Amber as well, it has its Promise API, look at
Promise class, so you can as well do:

(ec2 describeInstances: params)
then: [ :data | "success" ]
catch: [ :err | console error: err ]

Reply all
Reply to author
Forward
0 new messages