• Monday

    • Private work.
    • Back to nyc.
    • JS notes in gdoc.
    • Link another credit card save/connect tool.
    • Naiad, canid, canna, dacha.
    • Linkedin premium is ~$30/mo (individual).
    • Leetcode premium is ~$11/mo (annual sub, cyber monday deal). Dynamic layout, autocompletion, debugger, access to premium problems, access to some editorials, faster execution.
    • React.memo.
    • Supercontest.
      • AWS Billing and Cost Management.
        • Enabled cost optimization suggestions. Creates a role to access your other services, collects usage, gives realtime updates.
        • Opted into and played with Compute Optimizer.
        • Created a cost monitor and attached subscription (my email). Sends daily summaries and alerts if >50% above expected (a single day, I believe).
        • Created 4 budgets: 1 for monthly spend under a certain amount (actual AND projected), and 3 for each RI ensuring that utilization of the RI is 100%. All 4 email me if triggered.
      • VSCode SSH Remote.
        • Installed all extensions in the sbsc remote. Remember this is an installation on the remote.
        • It bricked the EC2 instance. Not sure which extension. Maybe one of the windows-specific ones?
        • Rebooted from EC2, connected, removed all vscode extensions (kept them local, uninstalled from ssh:sbsc).
        • Remember the disconnections could have been from my poor internet too. Just wait a few.
      • Remember you can make build-start-prod without losing any data, even if you restart or stop-prod manually, and that’s how it’s always been. BUT it USED to be the case that make down-prod would wipe the DB volume. Now that’s clean too – it persists in RDB, regardless if prod docker composition (just app+nginx) is downed.
      • ElastiCache.
        • Went through the app and added some view function cached and regular function memoize decorators.
        • Played with an initial memoization from flask-cli. Nothing was persisting. Ah – it’s because CLI uses NullCache. Changes so the prod flask cli connects to the prod elasticache (like it already does with rds).
        • Note: you cannot traverse sqla relationships from a cached object. The parent obj is not bound to a session, the dependents are dangling.
        • You can change this to subquery or selectin loading (rather than the default lazy, which queries at ACCESS time)(https://docs.sqlalchemy.org/en/20/orm/queryguide/relationships.html) or manually load all children on the dangling object with new queries, but then we defeat the whole purpose of a cache.
        • Memoized most of the functions in queries (as long as they return something, and something other than direct sqla objects). This should speed up some stuff like get_current_week(), is_regseason(), etc. TTL set to 30, since the intention for the memoization is intra-request optimization, not inter. Will do that with view caching next.
        • Also – you don’t really want to cache anything outside of query libs. I have lots of functionality in utils and other libs. But the point of the cache is to optimally save a db trip. If the other logic is a local compute op, up to a reasonable ceiling of time complexity, it’s faster than network-hitting redis anyway.
        • Added caching for the main view functions. Set TTL to 60 to match the frequency of the score fetch, the primary cache invalidator.
        • Skipped caching for API endpoints, stuff like /email-all-picks and /commit-scores.
        • Created followup ticket for event-driven cache invalidation (based on supercontest.dbsession.commits), rather than blanket time-driven TTLs right now.
        • Deployed to prod, tested, ready for MNF.
      • Created a new cost report for Amortized blending (takes the RIs and extends their costs in the daily/usage expenses). And then filtered RIs out of the main cost report for daily service totals.
      • Added paid users, now to 20. Expect 27 total.
        • There was an infinite recursion in the function that adjusts purses for ties. This occurred when there were only 4 people in the paid league. Not sure which ranks were tied.
        • Will debug this next time I see it.
      • Enabled some aws cost mgmt prefs: multi-year lookback at monthly granularity (up to 38mo), daily granularity for all services up to 14 day lookback (from 7, default).
  • Sunday

    • Private work.
    • Some more refreshers on (pandas, psql, dsa, js). Remember postincrement i++ (eval to val then increment) and preincrement ++i (increment then eval to val). And == vs === for strict type. Error. new.
    • AWS merge Billing with Cost Explorer -> Billing and Cost Management.
    • In redis, just EXPIRE <mykey> <ttl>. You can check with TTL <mykey>. Then flask-caching obviously allows you to plug into the redis api.
    • Supercontest. Found a bug in the parsing of the espn score API. Added to the ticket where I’m swapping those out.
  • Saturday

    • Private work.
    • Gitlab-runner runs on macbook even when vscode is closed; it’s running the container whenever the host is up. Remember it directly runs – not through a ubuntu container on wsl2 for my desktop.
    • Christmas shopping. Went through amazon (+other) black friday and cyber monday.
    • No-rush shipping options gets 6% back an prime visa (vs 5).
    • Played with mint a little. Remember moving to credit karma. Will fix solium connection etc at that time.
    • Increased credit limits.
    • Money moves.
    • AWS is paid by CSR. Remember auto/condo insurance are on doublecash.
    • There was an errant instacart+ subscription being charged to my citi card (my actual account is the chase one) since May.
      • Reached out to instacart help. Was transferred over 15 times lol. Syed A, Neelima P, Bishal D, Anthony M, Carol V, Tabrez P, Sumera S, Swetha S, Neelima P again, Amanda D, Khanyisile M. At this point, they turned off the notifications.
      • Then the fraud team just said “fill out this unrecognized-charges form and we’ll get back to you in 7-10 days” – unacceptable. https://www.instacart.com/secure_forms/unrecognized_charges.
      • Didn’t fill it out, instacart didn’t deserve the courtesy. Went to cc to dispute.
      • Citi’s dispute interface was “temporarily unavailable” and I couldn’t submit. Both great systems! Gonna cancel both citi and instacart after this trash.
    • Amazon reload $100, get 10% back, once.
  • Friday

    • Private work.
    • Remember gnumake’s variables are accessed with $(var). To grab shell variables, use $$var.
    • So you don’t have to set upstream on every new git branch: git config --global --add --bool push.autoSetupRemote true
    • Redis $5.62 on equitybee.
    • Added gitlab runners to my macbook so I can pass CICD while working remotely.
      • /srv doesn’t exist by default, so sudo mkdir /private/srv and chown it to you then run the usual two commands:
        • docker run -d --name gitlab-runner --restart always -v /private/srv/gitlab-runner/config:/etc/gitlab-runner -v /var/run/docker.sock:/var/run/docker.sock gitlab/gitlab-runner:latest
        • docker exec -it gitlab-runner gitlab-runner register
          • Then enter all the info. Token is from the “create new runner” screen on gitlab’s UI. Default image usually python:3.12. Executor type is docker.
        • Then just up the concurrency by editing /private/srv/gitlab-runner/config/config.toml on the host.
    • Pandas group_by, agg, more.
    • Supercontest.
      • Fixed the auth for redis-cli and the private conf file. It’s still clunky (sourcing secret then passing var). Redis-cli should absolutely provide native support for reading auth from a file.
  • Thursday

    • Private work.
    • Pandas .rank() method. Could be used for leaderboard stuff. .melt() is useful too.
    • Biggest spelling bee I’ve seen. 74 words, 462 points.
    • Amplify and Cognito getting a lotttt of hate: https://www.reddit.com/r/aws/comments/182kunk/which_is_the_most_hated_aws_service/. CodeCommit too, although no one uses.
    • 100% draws after 3 rounds in sinquefield.
    • Supercontest. Purchased RI for elasticache, 3yr upfront. A little over $7/mo, not bad.
  • Wednesday

    • Private work.
    • Some regex refreshers. Remember \b = word boundary (basically all characters except other letters/numbers/underscore.
    • More pandas. iloc, str.match
    • Sleeping poorly for about a week.
    • I should probably set up a gitlab-runner on my macbook? The desktop is not always running.
    • You can read variable definitions from a conf file and pass as env vars to a command.
      • Example in bash: (source <path/to/conf> && echo $<var_from_conf>)
      • The parentheses are obviously for a subshell. Then the env vars are defined ONLY in the subsequent command, not the host shell you’re running everything from.
    • For redis it’s more efficient to use SCAN than KEYS to list all keys.
    • Supercontest.
      • More with elasticache today. Played with flask-caching and the redis cluster.
      • Tested make sync-db-dev for the first time. Worked well.
      • Added a gnumake target to drop into the redis-cli.
      • Deployed all infra changes (deps, redis, flask-caching init, auth, app init, etc), as well as the queries/selects splitout.
      • Now just ready to ADD caching wherever appropriate (using flask-caching‘s decorators). And test.
      • Connect to the sbsc EC2 with vscode’s remote explorer for ide benefits (vs vim). Can have both windows open (wsl2 and remote), with separate terminals, etc.
      • Was getting gunicorn timeouts in prod after deployment.
        • The flask-caching default timeout is 300s. Gunicorn is 30, hence dying first.
        • No long running queries or anything. Happening on boot.
        • Confirmed redis-py is threadsafe, since I use gthread workers with gunicorn: https://redis-py.readthedocs.io/en/stable/advanced_features.html
        • So it’s a connection issue. Then simply times out.
        • Wrote a little script and debugged till I found it. Unlike host/pw/etc (directly exposed by flask-caching), redis-py expects ssl=True (which flask-exposes through the generic CACHE_OPTIONS).
        • My elasticache redis cluster requires tls, so it was quietly rejecting connections. Added the kwarg. Fixed.
      • Tested the PROB restore for the first time, from pg_restore. Still haven’t restored from an RDS snapshot.
        • Was failing at first. “relations/seq/PKs/etc already exists”.
        • Confirmed that --clean --create was being passed, as usual. So it should drop everything before restoring from a dump.
        • Worked fine in dev.
        • Maybe something in RDS doesn’t allow drops?
        • Nope. It was just that you can’t drop a db if there are open connections to it, so --clean was failing. In dev, I stop the app container before restoring. I had deleted that from prod. Added it back.
        • The line fetch was broken because (for the first time in 10 years) westgate added spaces between the team name and the asterisk for home. Fixed.
  • Tuesday

    • Private work.
    • More pandas. For join, use merge. Left, right, inner, outer. .unique(), .sort_values(), .drop_duplicates, more.
      • Remember to not use truthy operators (or, and, not) like usual in python. Use bitwise (|, &, ~).
    • Changed trays.
    • Beside Altman, Greg, Ilya – the other 3 board members were Adam D’Angelo, Tasha McCauley, and Helen Toner. They don’t work at OpenAI (Quora, Rand, and Georgetown). Tasha is also Joseph Gordon Levitt’s wife. I don’t think any have tweeted since? Although some private. Ilya/Altman/Greg have.
    • CZ pled guilty for money laundering, 50M fine, step down as binance CEO.
    • Gardening.
    • Had to relaunch the gitlab runner, and with --restart always so it boots when wsl2 boots (anytime the docker daemon restarts).
    • Registered for re:invent (next week).
    • Stacked 10-player sinquefield cup started today.
    • Supercontest.
      • All elasticache all day today – the implementation on the app side.
      • Remember in the old flask-caching infra: You query the db once. It stores the resultant objects in the cache. A second request for the same data in. The cache returns the objects. But the objects are dangling (not associated with a session), and could be wrong, so sqla rejects them. I no longer have to worry about this with the redis cache.
      • Made sure ALL reads were from the queries module and ALL writes were from the commits module. There is one exception: flask-user. This is already scheduled for cognito replacement.
      • Split into queries (wrappers, returning python types) and _queries (direct cache/db reads, returning sqla objects).
      • This whittles down the surface area of (direct data access) vs (the app’s manipulation of data in python). I’ll only cache the former, for now. Maybe later I can cache commonly accessed views / whatever.
      • Used flask-redis which plugs directly into the app factory pattern instead of managing my own redis object.
      • Hmmm, nope – not needed. flask-caching (the standard, what I was using before) supports this. It can connect to a redis cluster. And it can cache view functions, custom functions, memoize, cache jinja snippets, auto-create keys for all of those based on specific request paths, args, etc – and exposes direct set() and get() calls from redis.
      • Updated banner.