Skip to content

Instantly share code, notes, and snippets.

View searls's full-sized avatar
💚

Justin Searls searls

💚
View GitHub Profile

Running with patch

$ QUEUE_ADAPTER=async ./fix-preview-image-race-condition.rb 

Yields

Creating a post and uploading a video
@searls
searls / readme.md
Created January 31, 2024 16:15
Uncovered a race condition when multiple preprocessed variants are specified for a previewable attachment (e.g. PDF, videos) and multiple TransformJob jobs are enqueued after create

TIL this script helped me figure out that

  1. Given a previewable attachment (video, pdf) has 2 preprocessed variants
  2. After being attached, these are enqueued [ActiveStorage::AnalyzeJob, ActiveStorage::TransformJob, ActiveStorage::TransformJob]
  3. All 3 jobs will (I assume?) separately download the video from storage to a tmp file
  4. Running asynchronously, a race condition results: both transform jobs will see no blob.preview_image exists yet and will BOTH create one
  5. Since a blob only has one preview_image attached, one preview image (and any variants associated with it) will be orphaned
  6. As a result when the attachment is purged, those orphaned blobs and variant record will fail to be purged

Not awesome things that happen in this case:

@searls
searls / feeds_controller.rb
Created January 7, 2024 15:41
Abbreviated example code that was exhibiting an N+1 only for non-image (video/pdf) preview representations
class FeedsController < ApplicationController
def index
@posts = Post.with_visuals.order(published_at: :desc)
end
end
@searls
searls / github
Created November 16, 2023 02:11
I got sick of going through multiple steps to visit the current directory's github URL when I'm looking at a terminal, but I don't necessarily want to install `gh` or `hub` just for this feature.
#!/usr/bin/env ruby
begin
repo = `git remote -v`.split("\n").find { |line|
line.include?("github.com")
}.split("\t")[1].match(/git@github.com:(.*).git/)[1]
system "open https://github.com/#{repo}"
rescue
warn "No github remote found"
@searls
searls / run
Created October 17, 2023 15:03
LOL, I wrote a Ruby script for generating spreadsheets conversationally with GPT-4.
~/code/searls/spreadsheetify $ ./script/run
Let's define columns.
Column name:
> Name
Column description: (optional)
>
More columns? [Yn]
>
@searls
searls / feedback_loops.rb
Last active July 24, 2023 16:26
A script for illustrating feedback loops completed given various conditions for a post on https://justin.searls.co
WORKDAY_HOURS = 8
LOOP_SPEED = 15
INCORRECT_EVERY = 25
LOW_FIDELITY_EVERY = 10
INCORRECT_LOOP_PENALTY = 3
LOW_FIDELITY_TIME_PENALTY = 2
time_remaining = WORKDAY_HOURS * 60 * 60
@searls
searls / sorbet_override.rb
Created June 17, 2023 13:20
Sorbet's documentation doesn't give particularly elucidative examples of using the runtime check callbacks available to override Sorbet's default behavior, so here's an example of how I'm doing it in Mocktail.
# Override Sorbet's runtime checks inside a given block's execution to allow
# testing of, among other things, Mocktail's own runtime type checks.
# See doc: https://sorbet.org/docs/tconfiguration
#
# Note that the messages being raised are the same as those constructed in
# sorbet-runtime (0.5.10847)
#
# Example usage:
# def test_not_a_class
# e = SorbetOverride.disable_call_validation_checks do
# typed: true
# This script prints:
#
# <-- Stubbing based on kwarg comparison with a TYPED method
# Should be tim: "jan greeting"
# Should be jan: "jan greeting"
# Should be nil: "jan greeting"
# <-- Stubbing based on kwarg comparison with an UNTYPED method
@searls
searls / english.txt
Last active May 11, 2023 08:35
Ruby Kaigi 2023 - Matz Keynote Transcription. Includes Matsuda-san intro and sponsor presentations. Transcribed and Translated by OpenAI Whisper https://replicate.com/openai/whisper )
Welcome to Matsumoto. I mean, physically or virtually. We're so happy to have you here. I think I'm seeing a thousand people in front of me here in this venue. I think it's been a while. It's been a while. It's been like four years since we had this number of people in the Kaigi venue. Four years. I'd like to say thank you for gathering again, coming back to RubyKaigi. I feel like the Kaigi is back. Because of you. Because of you, in the venue. Because you are back. But actually, since there have been four years of blank period of Kaigi, I said you're back, but actually we should be having newcomers to the Kaigi. So, please let me know. Please tell me, who are the first-timers of RubyKaigi? I mean, raise your hand if you are coming to RubyKaigi for the first time. Thank you. Thank you for coming. We really welcome your attendance. So, one thing I'd like to tell you, I have to tell you is... Um... Not that. The COC thing, the Code of Conduct, the core of the conduct is be nice to each other. So, let us be nice
@searls
searls / chat_gpt_streaming_example.rb
Created April 18, 2023 22:33
net/http's `read_body` is all you need to read streaming responses from the ChatGPT API. No need for a gem dependency
require_relative "../config/environment"
uri = URI("https://api.openai.com/v1/chat/completions")
req = Net::HTTP::Post.new(uri)
req["Content-Type"] = "application/json"
req["Authorization"] = "Bearer #{ENV["OPEN_AI_API_KEY"]}"
req.body = JSON.dump({
model: "gpt-4",
max_tokens: 80,
messages: [{role: "user", content: "What's the best way to learn Ruby?"}],