Tuesday, December 07, 2021

How to "SSH" into an AWS EC2 Instance without SSH key

 This gives you terminal access to your EC2 instance. You will just need your AWS CLI setup, with permission to SSM. This is not really using "SSH". So the machine doesn't need SSH port open, nor need an SSH key to login.

1. Find out your EC2 instance id from AWS Console.

  Example instance idi-0f85466ff323216f8

2. Run the SSM command:

 aws ssm start-session --target i-0f85466ff323216f8

  This should give you a terminal to the instance.

How to "SSH" into an AWS ECS Fargate Instance

This works for Fargate or Farget_spot to get terminal access, using SSM. This is not really using SSH. Your ECS instance doesn't have to have SSH port open for this to work.

1. Enable ExecuteCommand on your ECS service.

    aws ecs update-service --service myservice-v2 --enable-execute-command --cluster mycluster --region us-east-1

2. Update the Task Role of the myservice-v2 with: FullSSMPermission

    To find out the name of the task role, use AWS console and find it listed under your ECS service)

3. Start a new task in that service, and remember its task id

    Usually this can be done by stopping a task and let autoscaling policy to bring up a new node. The newly started task will have the ExecuteCommand setting that you setup earlier. This makes it possible to get to its terminal.

    The task id looks like something in this format: 01b46facf93d44b2ba3e3cf296dcaa30

4. "SSH" into the new node by its task id.

    aws ecs execute-command --region us-east-1 --cluster mycluster  --task 01b46facf93d44b2ba3e3cf296dcaa30 --container myContainer --command /bin/bash --interactive

    This should give you a terminal to the Fargate node.

5. If you cannot ssh in, find out what's missing in your setting from this checker:

    https://github.com/aws-containers/amazon-ecs-exec-checker

    Install the missing libraries until your machine passes the checker.

Wednesday, December 01, 2021

Getting Started with Clojure - Quick Tutorial

How to run a clojure file from terminal?

 clj /tmp/my.clj


How Clojure to read from stdin?

(print (read-line))


How to pass a file through stdin to a Clojure program from terminal?

cat /tmp/input.txt | clj /tmp/my.clj


How to hello world in Clojure?

(print "hello")

How to read all lines from stdin? (assuming less than 500 lines)

(print (take-while some? (repeatedly 500 #(read-line) )))

How to define a variable? (a variable that doesn't change.. ok! a constant! )

(def n (read-line))

How to parse string in stdin to an integer?

(def n (Integer/parseInt (read-line)))


How to map a lambda function on a list?

(map count ["hello", "world"])


(map #(count %) ["hello", "world"])


How to map a lambda function on a list, and do many things with each item?


(map #(do (print "hello") (count %))  ["hello", "world"])


How to print hello 3 times?


(map println (repeat 3 "hello"))



How to get an element in a list?


(get ["hello", "world"] 1)


How to zip two lists? - concat two lists


(map vector [1 2 3] [4 5 6])


How to create a hashmap for look up?


(def lookup (zipmap [1 2 3] [4 5 6]))


How to get a value from a hashmap by key? - same as getting an element in a list

(get lookup 3)



How to define a function?


(defn add [a b] (+ a b))




Friday, April 09, 2021

Apollo GraphQL Client: The order of Persisted Query Link & Retry Link Matters

We enabled automatic persisted query on an app that uses Apollo GraphQL client to query GraphQL. GraphQL persisted query is implemented by Apollo as an effort to save bandwidth from avoiding submitting the query both every time: https://www.apollographql.com/docs/apollo-server/performance/apq/ This was easily enabled with

    link = createPersistedQueryLink().concat(link)

Though at most of time the queries were submitted with persisted query hash, strangely there are times when full requests without query hash are still submitted, and the error cannot be recreated following the referer page of the unexpected request. It suggests the unexpected requests happened only occasionally.

I noticed that our link included the RetryLink feature.

         link = concat(new RetryLink({attempts: {max:2}}), new HttpLink({uri, fetchOptions}))

 Since Retry Link concatenated only with HttpLink, it will only know to send full request. Thus, the correct concatenated order is RetryLink on the outside of the PersistedQueryLink.

          link = concat(new RetryLink({attempts: {max:2}}), createPersistedQueryLink(), new HttpLink({uri, fetchOptions}))

After reordering the link concatenation, the client started to work correctly with persisted query hash all the time.

Tuesday, January 12, 2021

Java InheritableThreadLocal Does not Work Well with ThreadPool

    One of the dev's brought up the topic of InhertiableThreadLocal, which is a ThreadLocal whose value is copied from the parent thread to local thread. This first appeared to be an amazing feature. However, in the fine text, it says:

“Whenever that thread creates a new thread (a child thread), the InheritableThreadLocal object is automatically updated so that the new child thread has the same value associated with it as the parent thread”

    It means the copying process only happens during the creation. The Parent Thread and Child Thread relation relies on creation. This becomes an issue when you are using a ThreadPool, where the threads are reused instead being created. Some other people also encountered this issue:

So in conclusion, InheritableThreadLocal is not a good idea. Use caution when you are working with it.

How else would I pass ThreadLocal values across thread?

    You will want to copy the values in ThreadLocal variables as a field of a Runnable in the constructor. This creates a context for your Runnable. In your Runnable.run(), apply the values in the context to the ThreadLocal variables again. The allows ThreadLocal to be copied over because the constructor runs in your caller thread, while Runnable.run() runs in the invoked thread.