Curious (Clojure) Programmer Simplicity matters

Menu

  • Home
  • Archives
  • Tags
  • About
  • My Talks
  • Clojure Tip of the Day Screencast
  • (Open) Source
  • Weekly Bits & Pieces
  • RSS

CloudFront Origin Access Control (OAC) and hosting public website in a private S3 bucket.

December 9, 2024
Table of Contents
  • 403
  • Why bother?
    • S3 data leaks
    • Broken windows
  • Got it - just get it done.
    • Static website hosting
    • CloudFront OAC
  • Where’s the catch?
    • Look harder
    • Epiphany: S3 website hosting playing tricks
  • How to fix it
    • Any gotchas?
  • Summary
    • Takeaways
    • Solution’s architecture - visually
  • Resources

What could go wrong when migrating a public S3 bucket with static website hosting to a more secure alternative using CloudFront Origin Access Control (OAC) and making the bucket private?


Continue reading →

CloudFront: the mysterious case of a missing If-None-Match header

September 3, 2024
Table of Contents
  • TL;DR:
    • TL;DR: Solution
  • WHAT?!?
  • WHERE & HOW (projects page and introducing ETag-based caching)
  • Interlude: the webapp deployment architecture
  • BUT (confused observer)
    • tcpdump-ing
  • WHY (AWS Support rendezvous)
  • THEN (If you didn’t fix it, it’s ain’t fixed)
  • HENCE (rolling sleeves up)
  • WHAT (CloudFront function)
    • Seeing is believing
  • Solution Architecture
  • Resources
    • CloudFront
    • MISC

For months, we’ve been suffering from mediocre performance of part of our website (codescene.io) due to inability to effectively cache expensive page loads. A large part of it was a problem with CloudFront I discovered in December 2023 after conversation with the AWS Support team. Here’s a story of solving this problem.


Continue reading →

DNS: on (not so obvious) recursive name resolution

June 11, 2024
Table of Contents
  • DNS resolver configuration
    • macOS DNS configuration
    • Linux DNS configuration
    • Side note: ssh vs host/nslookup/dig
  • DNS name resolution
    • tcpdump, yey!
    • Recursive DNS name resolution
    • 1. Starting at the root
    • 2. TLD (.cz) nameservers
    • 3. Asking the authority
  • Bootstrapping ("Root hints") and Chicken-egg ("Glue records")
    • 1. Root hints (bootstrapping)
    • 2. Glue records (solving the "chicken-egg" problem)
    • 2b. Glue records - sometimes yes, sometimes not?
  • Flushing DNS cache
    • Flushing the cache
    • Observing the cache (logs)
  • References
    • Learning about DNS
    • MISC
    • DNS configuration
    • Root name servers
    • Glue records
    • DNS cache

This is an experimental type of a blog post I call a "deep dive". It goes deeper than usual, it’s longer than my other posts, and it explores more aspects of the topic, trying to deepen your (and my) understanding of the subject (DNS resolution).


Continue reading →

p6spy - Spying on Your Database

October 19, 2023
Table of Contents
  • Meet p6spy
    • p6spy setup
    • p6spy logging configuration
    • Note about MariaDb
  • CodeScene DB Query Log
  • p6spy log
    • Stacktraces
  • Alternatives
    • Database logs
    • The REPL
  • References

Talking to a relational database with Clojure is relatively easy. There’s a great library next.jdbc for that. In legacy applications, you may encounter an older library, clojure.java.jdbc.


Continue reading →

Liquibase: custom database migrations with Clojure (without AOT)

October 15, 2023
Table of Contents
  • Liquibase Intro
    • Custom migrations
  • Custom migrations in Clojure
    • AOT
    • Problems with AOT
    • Getting rid of AOT (deftype)
    • Classloading gotcha
  • Credits
  • References

Liquibase Intro

Liquibase is a well-know tool for tracking, versioning, and deploying database schema changes.

It uses changelog files to list database changes in the form of changesets (SQL, XML, YAML, JSON), which consists of Change Types. Standard changsets use SQL or a DB-agnostic equivalent written in XML, YAML, or JSON.

Here’s an example of a very simple changset adding a new table with a single column:

<changeSet  id="1"  author="nvoxland">
    <createTable  tableName="company">
        <column  name="address"  type="varchar(255)"/>
    </createTable>
</changeSet>

Custom migrations

Sometimes, there’s a more complicated migration that’s very difficult or impossible to express in SQL (or its Xml/YAML/JSON equivalent). That is, you need to write actual code to perform the migration. In that case, Liquibase offers customChange Change Type.

To implement a custom migration you need to:

  1. Create a Java class that implements the liquibase.change.custom.CustomSqlChange or liquibase.change.custom.CustomTaskChange interface (showing only a subset of methods here):

    public class ExampleCustomTaskChange implements CustomTaskChange, CustomTaskRollback {
        private String helloTo;
        @SuppressWarnings({"UnusedDeclaration", "FieldCanBeLocal"})
        private ResourceAccessor resourceAccessor;
    
        @Override
        public void execute(Database database) throws CustomChangeException {
            Scope.getCurrentScope().getLog(getClass()).info("Hello "+getHelloTo());
        }
        @Override
        public void rollback(Database database) throws CustomChangeException, RollbackImpossibleException {
            Scope.getCurrentScope().getLog(getClass()).info("Goodbye "+getHelloTo());
        }
        ...
    }
  2. Compile the created class, package it into a JAR file, and then add it to a Liquibase classpath.

  3. Reference the class in your changelog:

    ...
    <changeSet id="21" author="nvoxland">
        <customChange class="liquibase.change.custom.ExampleCustomTaskChange">
            <param name="helloTo" value="world"/>
        </customChange>
    </changeSet>
    ...

Continue reading →
Next »

Copyright © 2025 Juraj Martinka

Powered by Cryogen | Free Website Template by Download Website Templates