- General knowledge of how software stacks (purpose of each part of the stack, how pieces talk to each other, pros, cons, tradeoffs, etc)
- Specific programming languages.
SyntaxHighlighter
Thursday, April 8, 2021
Tips for Dev Experience
Friday, January 15, 2021
Git connections while using PdaNet+
Sometimes we travel to my parents' place, who do not have internet or wifi.
| ~Me, basically |
We do have cell service, so working remote is possible. I use PdaNet+, a nice utility app for Android that turns my phone into a wifi hotspot on the MacBook. This works great for most everything that uses https. (Special ports, like a direct connection to Postgresql 5432 and the like do not work, likely blocked by phone carrier). This Wifi Direct connection on the Mac (Big Sur) requires a special proxy port, but then email clients and web browsers work great.
However, git was giving me problems. An error like this:
$ git pull
fatal: unable to access 'https://***@bitbucket.org/***/***.git/': Could not resolve host: bitbucket.org
All other http works, but this does not? Aaarrgh!!
The fix: Set the proxy directly in git as well (same that is needed in WiFi Network settings)
$ git config --add http.proxy http://192.168.49.1:8000
(don't forget to `git config --global --unset http.proxy` when done).
Now git works too. I'm living large on the edge of civilization : )
Edit: When using SSH Git (like BitBucket or GitHub required in 2022) the config has to be set another way. These lines were needed in ~/.ssh/config (and needed to be removed/commented when done)
ProxyCommand nc -x 192.168.49.1:8000 %h %p
ProxyCommand nc -X connect -x 192.168.49.1:8000 %h %p
Monday, September 28, 2020
ElasticBeanstalk HTTP Time
Web servers with NodeJS are fast, right? Yep, most of the time. The use case for our system is that users collect data with photos on their mobile app offline until they send their data. It's a nice hand-shake that the data exists on the device until the server receives it, so there is no data-loss and working offline was a requirement for the app. Typically an upload is a big JSON object and some photos. A few hundred K in most uploads. Recently one of our auditors keep a week's worth of data with a lot of photos, and gets a timeout when trying to send the data. 60 seconds and the upload fails. (We don't chunk it into multiple requests to maintain that handshake, and in 99.99% of the cases it is never a problem.)
We won't release a new mobile version for this single user, so the change needs to be made on the servers. Ours use ElasticBeanstalk, which is a fairly standard system setup, in that our traffic follows this flow:
LoadBalancer -> Instances, and each instance NGINX -> NodeJS
Lots of these stages can timeout on your HTTP requests, mostly by having a default. I have a testable HTTP request I made through Chome and watched the results in in the Dev Tools Network window. Initial testing died exactly at 60.
LoadBalancer
We are using AWS, so go to the EC2 service, on the left for Load Balancers, and change the "Idle Timeout."
NGINX
This could have two places to change, one is NGINX itself (which is really handling all the web traffic) and the other is the NGINX-Node proxy.
I made these changes in our server { context.
client_max_body_size 50M;
client_body_timeout 300s;
keepalive_timeout 300s;
send_timeout 300s;
And these in our location /api { (which is a proxy_pass to the nodejs upstream)
proxy_send_timeout 300s;
proxy_read_timeout 300s;
send_timeout 300s;
These NGINX directives are all documented here: http://nginx.org/en/docs/dirindex.html. The main thing is to allow the connection to live with NGINX and upload for a while (the server changes), and that NGINX will keep the connection to node for longer (the location changes). These all had timeouts 30s - 60s.
This worked well! My test action made it to 120s. This increased my previous timeout values, but still not 300s like the settings suggested.
NodeJS
The default Node http servers could have timeouts on two places. First is the default server timeout (120s) and the second is the client request timeout. The server timeout defaults to 0 in Node 13 (and though we are using v12.18 this one was not an issue). Each request can have a different timeout as well. I made our two problematic endpoints have a longer timeout this:
That was the final one. My test call actually completed in 4.3 minutes so the extended timings worked through the full system.
Tuesday, June 9, 2020
When did I start my Mac
You can try either one, and get some output like this:
A short list of useful activity with the time of day. Yay!
Wednesday, April 15, 2020
Integration Tests in Jest - Specific Group Serialization
Background
I like to write integration tests when testing my APIs (I find them the most meaningful) which typically has a group of API calls in a single test suite. User Permissions, Client Configurations, Business Processes, etc are tested together. Most times a folder contains the group of test for that suite, and tests are expected to run sequentially because the data created for the "create" api calls could be used for the "update" "read" and "destroy" API calls as well.Enter Jest. Every test file is able to run in parallel and the state is independent of the other tests. Serial in a single file and parallel across many files. Great for running all the tests, but makes it hard to share state between them. To group my API calls I could either:
- Put them all in a single file to test out the entire suite. Or...
- Build up some testing data before each suite runs.
I did not like #2 too much either - custom testing code to "build the data" at the start of each test, plus a 5 sec or so boot time for a backend API instance to start on the server. Smaller files leads to a lot of boots and a lot of time (even with extra cores and Jest workers). Perhaps a DB seed file could ensure certain data would be available, but that's as dynamic as building on the fly and it's one more thing to maintain for the test suite.
What Does Not Work
First, you cannot create a single, shared global to use across all your test suites. Lots of chatter about that here, but the summary is only JSON-serializable things can be global values. API tokens or WebSocket URLs? Sure. Instantiated objects with functions and all sorts of other initialized data, like an actionhero api instance? No way. Each test suite is running in its own worker thread, meaning it has its own scope and cannot "talk to" the others (and don't try because they're all running parallel which could lead to craziness!).
Second, and this is true for many Node test frameworks (Mocha for sure), is that test setup (the describes) is synchronous while test running (it(), test(), beforeEach(), etc) is asynchronous. For Jest, you cannot instantiate a variable inside a describe() block that you want to use in your tests. You can initiate a variable, but must instantiate inside a test() or beforeAll() function. The describe() functions all run at the start of testing synchronously, to setup what tests will run. The actual tests and variable instantiation happen when the test run, so if the variable was assigned in a describe() block, and not a test block, that assignment took place in the setup phase and likely does not contain what you expect it to (often leading to "cannot read property X of undefined" errors).
Solution
Here we have a single actionhero instance started before all the test suites are run, and stopped after. Describe blocks are run in the order they are defined, so we describe the suites here, but the contents are in other files and can define their own beforeAll() or afterEach() functions. The convention is that are in their own describe() block.
Be sure to put that __test__/lib directory in your ignore patterns, or Jest will try to run them.
It is possible to change "describe('Create', createTests)" to "createTests()" by changing the export of the create.ts to be like this:
I do not prefer it that way because some information would be hidden in 00-template-tests.ts, but it's an option!
You could probably do some fancy "walked directory" imports to find all the files in ABC order and include them in your suite - depending how large your suite grows or how annoying you find it to update the main test file.
That's how I'm running Jest tests in sequential groups, but maintaining parallel suites for all part of my API. Working for now, and I'll update this post if something goes terribly wrong : )
Thursday, June 13, 2019
Winston v2 to v3 and Papertrail Logging
Friday, November 16, 2018
The Senior
What is "The Senior"?
At a previous company, a large defense contractor, there was a technical progression for Software Engineers: Associate -> Engineer -> Senior -> Staff -> Senior Staff -> Principle. It went on from there but not many reached the higher ones. (Remember that previous CEO of mine? ; ) Being a "senior" at that company put you squarely in at a Level 3 Technical position, and was directly related to your experience, education and pay scale. Outside of these extremely large organizations, a "senior developer" means many different things. And it is not consistent among companies.Sometimes the title is self-defined. If someone thinks they are "senior" and can convince their boss or hiring manager the same, they'll get the title. Some companies have (loosely or strictly) defined criteria for what senior means, and some are too small to think about titles so it seems like people just make things up. I'm looking at you, "Chief Awesomeness Officer at New Startup Company." Everyone there gets a good title because both of you needed cool business cards : )
Is a senior based on experience in years? Skill? A gut feeling - "I know it when I see it." I've seen the title claimed by people that were skilled and/or experienced, but still felt something was lacking. They were good at what they did, but were they a senior in my eyes? Something seemed off, the title did not match.
Trust
- new team member/mentee?
- entire team?
- research project or incubator idea?
- maintain a legacy project that business critical?
- product roadmap?
- deadline?
- customer (interaction)?

