Yogesh Dhimate

Notes to Myself

Dec 30, 2020 - 4 minute read - Personal

How Intermittent Fasting Saved My Life

One of my goals for 2020 was to stick to an intermittent fasting routine. I completed 6600 hours of fasting in 2020. On average, that’s 18 hours of fasting every day, for 365 days. Other interesting stats include the longest streak of 440 fasts and the longest fast of 37 hours. I did reasonably well to maintain a healthy weight despite stress-induced binge eating during the pandemic.

My fasting journey started in mid of 2019. In the second half of July 2019, I was experiencing sharp pain in my left arm and shoulder. During that week in the middle of the night, I woke up all sweaty, with shortness of breath. I anxiously started googling for the nearest urgent care location, and the shortest path to reach there, just in case I need to rush. Fortunately in the next few minutes, I regained control of my breath. I drank a glass of water and decided to wait until morning. I visited my primary care physician the next day to find out what’s going on, and potentially plan for my angioplasty or bypass surgery (or whatever they do to fix the heart-related problem).

I like my doctor. He is not aggressive with any medications or prescriptions. His advice usually contains words like an embrace, adapt, or wait. After performing preliminary checks he confirmed that while the incident was indeed frightening, and showed all the symptoms of cardiac arrest, it was not a heart attack! The subsequent lipid profile tests etc confirmed his diagnosis.

While the diagnosis was good, when I carefully looked at the lab results, my LDL cholesterol was at the upper threshold of the safe range. My BMI was indicating that I was overweight. The pain in my left arm wasn’t completely gone. What if my doctor was wrong? This was a clue that I needed to make changes in my lifestyle. Fortunately, two things happened.

  1. I read an interesting article about magician Penn Gillette losing 100 pounds by fasting for 3 months. He essentially followed One Meal A Day approach to maintain the weight loss.
  2. I met a friend who had lost about 20 pounds in 3 months by following the intermittent fasting practice. It was super impressive.

I started taking deep dive into some internet research to understand the basics of intermittent fasting. While it looks like a modern fad, it has been practiced for centuries by various cultures and religions. For example, Hindu Lunar calendar has a 2-week schedule based on the full moon and new moon. On the 11th day after the full moon and new moon, one fasts from sunrise to sunset. That’s twice a month. It’s called Ekadashi fast.

The physiology of fasting is fascinating. Once you have the food, the digestion kicks in, and food breaks into glucose, amino acids, and fatty acids. Ghrelin or the ‘hunger hormone’ decreases and insulin increases. Insulin carries the nutrients into cells to be stored as glycogen, fat, etc., or used as energy. This phase - anabolic - lasts for 4 hours.

After the anabolic phase, the catabolic phase kicks in. For the next 12 hours, your blood glucose continues to drop and the liver starts breaking down glycogen for energy.

The catabolic phase transitions to the fat-burning phase. That’s 16 hours after you ate. As the name indicates, during the fat burning phase fat stores break down for energy. The fat burning phase lasts for 8 hours and transitions into the ketosis (and the deep ketosis phase).

graph LR Z("fa:fa-hamburger")-.->A(Anabolic) A(Anabolic) -. 0-4

hrs .-> B(Catabolic) B(Catabolic) -. 4-16

hrs .-> C(Fat
Burning) C(Fat
Burning) -. 16-24

hrs .-> D(Ketosis) D(Ketosis) -. 24-72

hrs .-> E(Deep
Ketosis)

I will not go into a lot of technical details here. That’s the basic overview of the physiology of fasting.

Coming back to the point. In August 2019, I started my fasting journey with a 16/8 schedule which meant 16-hour fasting and an 8-hour eating window. Just within a week or so I got used to it. I found it too easy, then I transitioned to the 18/6 schedule. And eventually settled on the 20/4 schedule for most of 2019. I use Zero Fasting to keep me motivated. I got the results I hoped for and did not experience any pain in my left arm or shoulder since then.

Note: To put in Penn Gillette’s words. If you take health and nutrition advice from a random internet stranger. You are an idiot.

Dec 29, 2020 - 3 minute read - Programming

Upload Attachments to Salesforce Using MuleSoft

This question comes up occasionally in my conversations with customers. Often there is a need to programmatically upload an attachment (a pdf or an image) file to Salesforce using MuleSoft. If the integration developer is not very familiar with the Salesforce Platform, it usually confusing due to the way Salesforce manages the attachments.

As shown in the following ER diagram, there are multiple entities involved in storing and managing the attachments in Salesforce

erDiagram ContentDocument ||--|{ ContentDocumentLink : has ContentDocument { string Id string Title string PathOnClient date CreatedDate } ContentDocumentLink ||--|| Account : linkedEntity ContentDocumentLink { string Id reference LinkedEntityId reference ContentDocumentId picklist ShareType picklist Visibility } Account { string Id string AccountNumber } ContentDocumentLink ||--|| Contact : linkedEntity Contact { string Id string FirstName string LastName } ContentDocumentLink ||--|| sObject : linkedEntity sObject { string Id string SomeProperty }
Things to note:

  • Salesforce attachments are stored in ContentDocument (and ContentVersion) objects.
    • The ContentDocument object is used to retrieve, query, update and delete the latest version of a document.
    • The ContentVersion object is used to create, query, retrieve, search, edit, and update a specific version of a Salesforce CRM Content document.
  • The attachment is stored in ContentDocument (Or ContentVersion) and linked to any sObject (Contact, Account etc) via ContentDocumentLink Object
  • Thus, to successfully upload an attachment to Salesforce following needs to happen
    • Upsert an attachment (file) to ContentDocument/ContentVersion object
    • Query the ContentDocument/ContentVersion to get the ContentDocumentId
    • Use the ContentDocumentId to link to your sObject (Account, Lead Opportunity, etc) by upserting the relationship in the ContentDocumentLink object

Following flow chart shows the general approach to upload an attachment to Salesforce:

graph TD A([Start]) -->B[/Get file/] B --> C{{Prepare ContentDocument}} --> D[(
Create
ContentDocument)] D --> E{{Get ContentDocument Id}} E --> F{{Prepare ContentDocumentLink}} F --> G[(
Create
ContentDocumentLink)] G --> H([End])

Mule DSL code to achieve this

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
    <sub-flow name="Upload Attachment">
        <ee:transform 
            doc:name="Prepare ContentDocument">
            <ee:message>
            <ee:set-payload>
            <![CDATA[%dw 2.0
                output application/java
                ---
                [
                    {
                        Title: "filename" //Replace this with actual filename,
                        PathOnClient: "filename" //Replace this with the path on storage system
                        VersionData: payload.content as Binary {class: "byte[]"}
                        //This is the attachment content
                    }
                ]
                ]]>
            </ee:set-payload>
            </ee:message>
        </ee:transform>
        <salesforce:create type="ContentVersion"
            doc:name="Create ContentDocument"
            config-ref="Salesforce_Config"/>
        <ee:transform doc:name="Get Attachment Id">
            <ee:variables>
                <ee:set-variable variableName="contentVersionId">
                    <![CDATA[%dw 2.0
                    output application/java
                    ---
                    payload[0].id
                    ]]>
                </ee:set-variable>
            </ee:variables>
        </ee:transform>
        <salesforce:query 
            doc:name="Get ContentDocumentId"
            config-ref="Salesforce_Config">
            <salesforce:salesforce-query>
                SELECT ContentDocumentId From ContentVersion Where Id = ':contentVersionId'
            </salesforce:salesforce-query>
            <salesforce:parameters>
            <![CDATA[#[
                output application/java
                ---
                {
                    "contentVersionId" : vars.contentVersionId
                }
            ]
            ]]>
            </salesforce:parameters>
        </salesforce:query>
        <ee:transform doc:name="Prepare ContentDocumentLink">
            <ee:message>
                <ee:set-payload>
                    <![CDATA[%dw 2.0
                    output application/java
                    ---
                    [
                        {
                            LinkedEntityId: vars.accountId,
                            ContentDocumentId: payload[0].ContentDocumentId,
                            ShareType: "I"
                        }
                    ]
                    ]]>
                </ee:set-payload>
            </ee:message>
        </ee:transform>
        <salesforce:create 
            doc:name="Create ContentDocumentLink"
            config-ref="Salesforce_Config"
            type="ContentDocumentLink" />
    </sub-flow>

With this approach you can easily upload attachments to Salesforce.

Dec 24, 2020 - 2 minute read - Books

Made to Stick and the Curse of Knowledge

I recently read “Made to Stick” by Chip Heath and Dan Heath. It was a fun and quick read. While I liked their framework of SUCCESs (Simple, Unexpected, Concrete, Credible, Emotional, Stories) to get the idea to stick, I thoroughly enjoyed the explanation of the Curse of Knowledge. The curse of knowledge occurs when a knowledgeable individual/expert assumes that the others have the background to understand a specific concept.

According to Chip and Dan, In general, getting your message across has two stages - the Answer Stage, and the Telling Others Stage. In the Answer Stage, you use your expertise to arrive at the idea that you want to share. This involves studying the material and becoming capable of answering. However, the same factors that worked to your advantage in the Answer Stage will backfire on you during the Telling Others stage. To get the answer, you need expertise, but you can’t dissociate expertise from the Curse of Knowledge. You know things that others don’t know, and you can’t remember what it was like not to know those things. So when you start sharing the answer, you’ll tend to communicate as if your audience were you.

This reminds me of another news I read a long time ago about an audio illusion. Once our brains know what to expect to hear, they do, even if, in reality, it is impossible.

Dec 21, 2020 - 2 minute read - Programming

MuleSoft Capacity Explanation for Noobs and CXOs

I was talking to a C-level executive the other day and he asked me to explain how does MuleSoft’s capacity/sizing across various deployment models work. Given I always wear my technical hat I jumped right into the concept of cores and virtual cores and containers (and Kubernetes!) and did a pretty bad job. Fortunately, that executive was very accomodating and somewhat understood what I was talking about. Nevertheless, I should’ve done better.

I was thinking about this conversation over the next couple of days and decided to explain it to my wife - who is very non-technical.

Think of MuleSoft as a specialty cookie store. Or even better, think of Salesforce as a big giant grocery store, with a bakery section called ‘MuleSoft’. MuleSoft specializes in cookies. They offer 3 types of options to buy their fantastic product.

  • Cloudhub: Pre-baked cookies, these come in boxes. Very light and crispy. Rightfully branded as ‘Cloudhub’. You can buy as many boxes as you want. Each box contains 10 cookies. This means with one box you can feed 10 guests. If you have more guests coming over, or some guests are unusually hungry you can buy more boxes. There is also an allergen/gluten free version of pre-baked cookies for government guests.
  • Hybrid: A cookie dough to bake your cookies in your oven. The cookie dough is branded as ‘On-premise / Hybrid’. You can decide how big (or small) each cookie can be. You can make as many cookies as you want with the dough. (No more 10 cookies per box restriction!). Of course, some guests will find your ridiculously small sized cookies unappetizing (or funny).
  • Runtime Fabric: After some guests complained that pre-baked cookies were too big, and ‘make your own cookies’ unappetizing. MuleSoft started offering ‘Runtime Fabric’ branded cookie dough. You still have to bake your cookies, but the sizes of cookies are standardized. They won’t look funny.

Oct 24, 2017 - 2 minute read

Google Spreadsheets and ArrayFormula for XIRR Calculation

I was looking for a simple way to calculate performance of my investments over time. Popular portfolio trackers like Moneycontrol and Value Research did not meet my needs. So I decided to try out Google Spreadsheets. Nice thing with Google Spreadsheets is its support for import and queries. e.g. AMFI India publishes daily NAV’s on their website http://portal.amfiindia.com/spages/NAV1.txt You can import the data programmatically and run a query on it to find desired NAV. I can use following simple query to check the latest NAV of Birla Sunlife Frontline Equity fund, whose symbol is INF209K01YY7

=QUERY(SPLIT(QUERY(importDATA("http://portal.amfiindia.com/spages/NAV1.txt"),
"SELECT * Where Col1 like '%INF209K01YY7%'"),";"), "Select Col5")

Google Spreadsheets obviously supports data from Google Finance with its built in function GOOGLEFINANCE

=GOOGLEFINANCE("SBIN","price")

This will return latest price for State Bank of India. You can also use Stock Exchange assigned ID’s to query the data from Google Finance

=GOOGLEFINANCE("500510","price")

This will return latest price for Larsen and Tubro. However the most killer feature of Google Spreadsheets is its support for ArrayFormula in conjunction with XIRR. Let me explain. Consider following cash flow.

A B C D
1 Transaction Symbol Date
2 Sell Havells 31/12/2017
3 Buy Havells 01/01/2017
4 Buy Havells 06/01/2017

We have to update the XIRR formula to include the new transaction we just added in our cash flow

=XIRR(D2:D4,C2:C4)*100
Symbol XIRR
Havells 4.493

This is very cumbersome to update XIRR formula, if you have a diversified portfolio with 10+ symbols and investing on a regular basis.

A B C D
1 Transaction Symbol Date
2 Sell Havells 31/12/2017
3 Buy Havells 01/01/2017
4 Buy Havells 06/01/2017
2 Sell SBI 31/12/2017
3 Buy SBI 01/01/2017
4 Buy SBI 06/01/2017
Havells =XIRR(D2:D4,C2:C4)*100
SBI =XIRR(D5:D7,C5:C7)*100

You can see for two symbols we have to keep close track of cell numbers etc to accurately calculate XIRR. ArrayFormula provides nice workaround to simplify and automate this process of using XIRR formulas for a growing number of transactions

https://support.google.com/docs/answer/3093275?hl=en

Enables the display of values returned from an array formula into multiple rows and/or columns and the use of non-array functions with arrays.

XIRR can be easily combined with ArrayFormula like below

=ArrayFormula(XIRR((B2:B7="HAVELLS")*D2:D7,C2:C7))*100
=ArrayFormula(XIRR((B2:B7="SBI")*D2:D7,C2:C7))*100

As you can see that except the symbol name both the formulas are identical. We can remove the hard coded symbol name and refer to the cell which has symbol name. Using ArrayFormula in the portfolio tracker has simplified maintenance of the spreadsheet and saved quite a few hours for me.