Behaving like the character in a story

I enjoyed reading Robert Kolker’s “Who Is the Bad Art Friend?”, specifically about the non-symmetric relationships of fiction and inspiration.

Larson’s biggest frustration with Dorland’s accusations was that they stole attention away from everything she’d been trying to accomplish with this story. “You haven’t asked me one question about the source of inspiration in my story that has to do with alcoholism, that has to do with the Chinese American experience. It’s extremely selective and untrue to pin a source of a story on just one thing. And this is what fiction writers know.” To ask if her story is about Dorland is, Larson argues, not only completely beside the point, but ridiculous. “I have no idea what Dawn is thinking. I don’t, and that’s not my job to know. All I can tell you about is how it prompted my imagination.”

When Larson discusses “The Kindest” now, the idea that it’s about a kidney donation at all seems almost irrelevant. If that hadn’t formed the story’s pretext, she believes, it would have been something else. “It’s like saying that ‘Moby-Dick’ is a book about whales,” she said. As for owing Dorland a heads-up about the use of that donation, Larson becomes more indignant, stating that no artist has any such responsibility. “If I walk past my neighbor and he’s planting petunias in the garden, and I think, Oh, it would be really interesting to include a character in my story who is planting petunias in the garden, do I have to go inform him because he’s my neighbor, especially if I’m still trying to figure out what it is I want to say in the story? I just couldn’t disagree more.”

“[Dorland] might behave like the character in my story,” [Larsen] said. “But that doesn’t mean that the character in my story is behaving like [Dorland].”

Captain Awkward also had memorable advice:

Creatively speaking, I think you can generally write whatever you want about whoever you want. You do not owe people flattering portrayals in your fiction and you don’t owe the world a fair hearing of both sides. Even if you’re writing memoir, the expectation is that you’ll write the truth about your own experiences and recollections of events. So, when it’s just you and a blank page that nobody else will see? Name names. Settle scores. Spill some beans. Layer in all the carefully hoarded observations and details you’ve been saving up. You don’t have to solve publishing problems right this second, so feed the fire in your belly with your ex’s pet name for himself if that’s what gets it done; spite is motivating. You can always pull up a name generator later when you need to.

Ethically speaking, being free to write whatever you want does not mean being free of consequences from what you wrote. If you include recognizable details about real people in your published writing, fictional or otherwise, if you disclose confidential information about them (like mental health diagnoses), assume that somebody will connect the dots, and assume that the people you wrote about will eventually feel some kind of way about it. They may not have grounds to sue you, but they might think you are a bad person or a lazy artist, and they might tell their own stories where you are not the hero.

Home buyer letter

Having now successfully purchased a home in San Francisco, I have had friends asked me for resources. This was the letter we sent to the seller, which is very SF, but also the energy to bring. I also learned that these letters are waning because they are biased af.

Dear [seller],

Your home at [street address] is the right fit for us, our two cats, and (hopefully) our future family. We love the long layout, high ceilings (we’re both tall) and sunny patio, and look forward to hosting friends for Sunday brunch someday.

We’re rooted in the city through the South End Rowing Club, St. Francis Lutheran Church, supporting the YMCA, kickstarting local businesses like Andytown coffee, and working at tech companies and nonprofits. Ben worked for three years just around the corner at California and Grant, and Angelina has worked at numerous tech companies around Union Square and SOMA. We love the quiet contrast of Nob Hill against the rest of downtown San Francisco.

We see SF as a long term home and [street address] as a homebase for work and play: swimming and rowing on the SF Bay, and wine trips up to Napa and Sonoma too. Your home would have the perfect commute for Ben, walking down the hill to his nonprofit job at [organization] where he builds technology to help people apply for food stamps, remove marijuana convictions from criminal records, and improve how government delivers services to those who need them most. And it’s a short walk for Angelina to the [company] Shuttle or Downtown SF [company] office where she does business development for maps and location technology in use around the world.

Your home would provide the greatest fit for us as we aim to continue to contribute to the fabric of the city, where we hope to raise a family and be active in the community. We aim to take great care of an already-loved property while advocating for a neighborhood that supports all members throughout the growth of our city.

Our offer is fair given the condition, amenities and comparable sales, and we aim for being the best buyer to steward this home and the neighborhood. We look forward to your consideration of our offer for [street address].

Sincerely,
Ben and Angelina

GoodJob, what’s new: Cron, concurrency controls, and a dashboard demo (v1.12.0)

This is a quick roundup of what’s new with GoodJob v1.12.0 since the last update published for GoodJob v1.9.

GoodJob ( github ) is a multithreaded, Postgres-based, ActiveJob backend for Ruby on Rails. If you’re new to GoodJob, read the introductory blog post.

For further details on the following updates, check out GoodJob’s Changelog or Readme.

Cron-like replacement for repeating/recurring jobs

GoodJob now ships with a cron-like replacement for repeating/recurring jobs. The cron-like process runs either via the CLI, or async within the web server process. Repeating jobs can be scheduled to the second, powered by the Fugit gem. Here’s what the configuration looks like:

# config/environments/application.rb or a specific environment e.g. production.rb

# Enable cron in this process; e.g. only run on the first Heroku worker process
config.good_job.enable_cron = ENV['DYNO'] == 'worker.1' # or `true` or via $GOOD_JOB_ENABLE_CRON

# Configure cron with a hash that has a unique key for each recurring job
config.good_job.cron = {
  # Every 15 minutes, enqueue `ExampleJob.set(priority: -10).perform_later(52, name: "Alice")`
  frequent_task: { # each recurring job must have a unique key
    cron: "*/15 * * * *", # cron-style scheduling format by fugit gem
    class: "ExampleJob", # reference the Job class with a string
    args: [42, { name: "Alice" }], # arguments to pass; can also be a proc e.g. `-> { { when: Time.now } }`
    set: { priority: -10 }, # additional ActiveJob properties; can also be a lambda/proc e.g. `-> { { priority: [1,2].sample } }`
    description: "Something helpful", # optional description that appears in Dashboard (coming soon!)
  },
  another_task: {
    cron: "0 0,12 * * *",
    class: "AnotherJob",
  },
  # etc.
}

Concurrency controls

GoodJob now offers an ActiveJob extension to provide customizable limits on the number of jobs enqueued or executed concurrently. Rails might upstream it too. Here’s how to configure it:

# app/jobs/my_job.rb
class MyJob < ApplicationJob
  include GoodJob::ActiveJobExtensions::Concurrency

  good_job_control_concurrency_with(
    # Maximum number of jobs with the concurrency key to be concurrently enqueued
    enqueue_limit: 2,

    # Maximum number of jobs with the concurrency key to be concurrently performed
    perform_limit: 1,

    # A unique key to be globally locked against.
    # Can be String or Lambda/Proc that is invoked in the context of the job.
    # Note: Arguments passed to #perform_later must be accessed through `arguments` method.
    key: -> { "Unique-#{arguments.first}" } #  MyJob.perform_later("Alice") => "Unique-Alice"
  )

  def perform(first_name)
    # do work
  end
end

Dashboard Demo

Don’t take my word for what a good job it is. Check out the new GoodJob Dashboard demo running on Heroku entirely within a single free dyno: https://goodjob-demo.herokuapp.com/

More news:

  • Wojciech Wnętrzak aka @morgoth became a GoodJob maintainer.
  • Wrote up details of the evolving development philosophy behind GoodJob.
  • The Dashboard now allows removing jobs, with more actions coming soon.

Contribute

Code, documentation, and curiosity-based contributions are welcome! Check out the GoodJob Backlog , comment on or open a Github Issue, or make a Pull Request.

I also have a GitHub Sponsors Profile if you’re able to support GoodJob and me monetarily. It helps me stay in touch and send you project updates too.

Paranoid and Reparative readings

From How Twitter can ruin a life: Isabel Fall’s sci-fi story “I Sexually Identify as an Attack Helicopter” drew the ire of the internet:

The delineation between paranoid and reparative readings originated in 1995, with influential critic Eve Kosofsky Sedgwick. A paranoid reading focuses on what’s wrong or problematic about a work of art. A reparative reading seeks out what might be nourishing or healing in a work of art, even if the work is flawed. Importantly, a reparative reading also tends to consider what might be nourishing or healing in a work of art for someone who isn’t the reader.

GoodJob Updates v1.5 - v1.9: Dashboard, daemonize, async_server, and graceful shutdowns

This is a quick roundup of what’s new with GoodJob since the last update published for GoodJob v1.4.

GoodJob (github) is a multithreaded, Postgres-based, ActiveJob backend for Ruby on Rails. If you’re new to GoodJob, read the introductory blog post .

For further details on the following updates, check out GoodJob’s Changelog or Readme.

GoodJob v1.5: Web Dashboard and configuration

GoodJob ships with a web dashboard to display future, finished and errored jobs for easy inspection. The Dashboard mounts as a self-contained Rails Engine.

GoodJob uses more Rails.application.config... for improved autoloading compatibility; deprecation notices have examples for updating configuration.

GoodJob v1.6: Daemonize

GoodJob can run as a backgrounded daemon for folks who are still managing servers with --daemonize.

GoodJob v1.7: Scheduled job cache

GoodJob caches scheduled jobs (i.e. ExampleJob.set(wait: 30.minutes).perform_later) for signifiantly improved latency without relying upon polling.

GoodJob v1.8: Graceful shutdown

GoodJob added additional shutdown options, including GOOD_JOB_SHUTDOWN_TIMEOUT to allow jobs to finish before exiting.

GoodJob v1.9: async_server mode

GoodJob added an additional async execution mode to simplify the default configuration: running jobs as part of the web-process (and not console, Rake commands, etc.)

Upcoming: cron and concurrency controls

GoodJob will add support for cron-style repeating jobs, and concurrency controls to ensure that only a specified number (1 or more) jobs are enqueued or performed at the same time. I previously was opposed to extending ActiveJob’s interface, but have changed my mind; it’s on!

Contribute

Code, documentation, and curiosity-based contributions are welcome! Check out the GoodJob Backlog, comment on or open a Github Issue, or make a Pull Request. Thank you!!! to everyone who has contributed to GoodJob, including morgoth, tedhexaflow, weh, lauer, reczy, zealot128, gadimbaylisahil, Mr0grog, thilo, arku, sj26, jm96441, thedanbob, and joshmn.

I also have a GitHub Sponsors Profile if you’re able to support GoodJob and me monetarily. It helps me stay in touch and send you project updates too.

Is SecureRandom.choose the wrong name for generating randomized strings with Ruby?

I frequently need to generate a short, random string:

  • I need a non-numeric, non-enumerable url ID. e.g. https://example.com/resources/TOKEN
  • I need to generate a short, human-readable random activation token and I don’t want it to contain similar-looking characters like 1I or O0
  • I want to do something fun with strings of emojis.

I’ve been copy-pasting this snippet around for years:

def random_string(alphabet:, length:)
  Array.new(length) { alphabet.chars[rand(alphabet.chars.size)] }.join
end

random_string(alphabet: "AaBbCc123", length: 7) 
# => "C113A11", "Abcc3B2", "33cabbC", etc.

random_string(alphabet: "😀😍🙃🤪😎", length: 3)
# => "😍😀😎", "😀🤪🤪", "🙃😎😀", etc.

The gems friendly_id and uniquify can do this too.

There was recently a discussion on Ruby on Rails Link Slack about generating random strings, and I went looking to see if there was a better implementation.

I found SecureRandom.choose, which is built into the Ruby standard library, and as part of the SecureRandom module, should be fairly trustworthy. Looks perfect:

# SecureRandom.choose generates a string that randomly draws from a source array of characters.
#
# The argument _source_ specifies the array of characters from which to generate the string.
# The argument _n_ specifies the length, in characters, of the string to be generated.
#
# The result may contain whatever characters are in the source array.
#
#   require 'securerandom'
#
#   SecureRandom.choose([*'l'..'r'], 16) #=> "lmrqpoonmmlqlron"
#   SecureRandom.choose([*'0'..'9'], 5)  #=> "27309"

…but there is a problem: SecureRandom.choose is a private method. The choose method is used to implement the public SecureRandom.alphanumeric method, but is not itself exposed publicly. I went back to the initial feature request and found the reason:

I feel the method name, SecureRandom.choose, doesn’t represent the behavior well.

Fair enough. Until the name is figured out, I’ll still be using it:

require 'securerandom'

SecureRandom.send :choose, "😀😍🙃🤪😎".chars, 3
# => "😍😎😍"

Generic advice for managers

From Allison Green’s Ask a Manager: “I Got a Terrible Review on Glassdoor, and I’m Spiraling”:

The reality is, when you’re a manager, not everyone will like working for you. You could be the greatest boss in the world and some people still wouldn’t like you. Partly that’s because being a good manager means giving feedback, addressing problems, and holding people accountable in ways they might not like. If you need to correct someone a lot, or have difficult conversations with them about their work, or say no to something they wanted, it’s human nature that you might not end up being their favorite person. Or you might have a style that doesn’t align well with theirs — maybe you’re very direct and matter-of-fact and that feels brusque to them, or maybe you’re a planner and a devotee of process and they work more spontaneously. That wouldn’t mean either of you is in the wrong; it would just mean you don’t mesh well together.

Sometimes, too, people dislike a job or a manager for reasons that aren’t as much about the manager as they are about other things going on with that person — a dislike of their career path, stressors outside of work, a generally bad fit with the role, or all kinds of things.

Or, frankly, you might be an imperfect manager — most of us are — but that doesn’t mean you’re a horrible one. Managing people is hard, and every manager will get things wrong now and then. Ideally you’ll establish a track record of fairness, transparency, and good judgment so your mistakes are judged within that context … but you still might encounter an employee who judges your mistakes harshly. You’re basically on a stage when you’re the boss; you’re going to be scrutinized by the people under you, and there will be things they take issue with. It’s part of the job, and you’ve got to be okay with that.

Or, yes, you might be a terrible manager! It’s possible. There are lots of terrible managers out there. But I’m skeptical that you’re terrible in the specific ways the review described (mean and intolerant of mistakes), because your detailed explanation of your approach to mistakes sounds pretty healthy and because you sound genuinely thoughtful and caring toward team members. People can delude themselves, of course, and managers aren’t always reliable narrators of their own management styles. But the way you talk about how you operate — and your reaction now — doesn’t seem to line up with that review or with the feedback people have given your boss about you. That doesn’t mean that review is definitely wrong. I obviously can’t say that with certainty. But I don’t think it warrants the self-flagellation you’re doing.

That said, all managers have ways they could improve — things they’re doing that irritate or upset their teams, or make things run less effectively, or allow problems to fester. I can say with confidence that you could be a better manager, because we all could. So one option is to take this as an impetus to do a real inventory of the way you manage, figure out where you could improve, and lean into doing that work.

GoodJob 1.4: JRuby compatibility and more

GoodJob version 1.4 is released. GoodJob is a multithreaded, Postgres-based, ActiveJob backend for Ruby on Rails. If you’re new to GoodJob, read the introductory blog post .

GoodJob’s v1.4 release adds support for:

  • JRuby
  • MRI 3.0
  • Rails 6.1
  • Postgres 12+

And includes additional improvements to the Web Dashboard.

Version 1.4’s release comes three months after v1.3 and five months after GoodJob’s initial v1.0 release.

JRuby compatibility

GoodJob 1.4 adds compatibility for Ruby on Rails applications running under JRuby. GoodJob’s multithreading is built on top of ConcurrentRuby, which provides consistent behavior and guarantees on all four of the main Ruby interpreters (MRI/CRuby, JRuby, Rubinius, TruffleRuby).

A minor downside of JRuby is that JRuby’s database adapter, activerecord-jdbc-adapter, does not support Postgres LISTEN, which means GoodJob must rely on polling for new jobs under JRuby.

Broader compatibility and improvements

In addition to JRuby, GoodJob 1.4 adds compatibility for MRI 3.0, Rails 6.1, and Postgres 12+.

GoodJob 1.4 also includes improved filtering for the Web Dashboard,.

What’s next

The next version of GoodJob will add support for daemonization.

Contribute

Code, documentation, and curiosity-based contributions are welcome! Check out the GoodJob Backlog , comment on or open a Github Issue, or make a Pull Request.

I also have a GitHub Sponsors Profile if you’re able to support GoodJob and me monetarily. It helps me stay in touch and send you project updates too.

Triangular eating

I have been practicing triangular eating after reading this blog post from The School Lunch Project in 2010:

Triangular Eating (sankaku-tabe)

(ex.) Main dish → Rice or Bread or Pasta →Soup →Main dish → Rice or Bread or Pasta → Soup….

In Japan, we usually learn how to eat food in triangular patterns when we were little kids. We usually learn it preschool age to elementary school age. When we start school lunch, it is the time to learn how to eat. It is kind of Japanese food culture, so teacher don’t go too strict nowadays. Kids don’t have to eat in triangular way, but many Japanese do triangular eating because we learn when school lunch time.

I would like to tell about the triangular way of eating. So, you have to make sure it is in triangular order. This is good practice in learning know how to eat a balanced meal by yourself. I think you can arrange this as square, pentagon and so on. Please go ahead add a salad or a side dish. As time goes by, if I have meat or fish, I automatically want to eat rice, then I start to want to eat vegetables. Isn’t it nice?

Also, triangular way could be give you rhythm and let your mouth reset. You can imagine wine and cheese. It is work well for harmony too.

The five ideals explained

I previously posted the The Three Ways from The Phoenix Project. Here are the Five Ideals from The Unicorn Project, by way of Gene Kim’s IT Revolution blog:

The First Ideal: Locality and Simplicity

We need to design things so that we have locality in our systems and the organizations that build them. We need simplicity in everything we do. This ideal relates to the degree to which a development team can make local code changes in a single location without impacting various teams. The last place we want complexity is internally, whether it’s in our code, in our organization, or in our processes.

The Second Ideal: Focus, Flow, and Joy

The Second Ideal is all about how our daily work feels. Is our work marked by boredom and waiting for other people to get things done on our behalf? Do we blindly work on small pieces of the whole, only seeing the outcomes of our work during deployment when everything blows up, leading to firefighting, punishment, and burnout? Or do we work in small batches, ideally single-piece flow, getting fast and continual feedback on our work? These are the conditions that allow for focus and flow, challenge, learning, discovery, mastering our domain, and even joy. This is what being a developer means.

The Third Ideal: Improvement of Daily Work

The Third Ideal addresses paying down technical debt and improving architecture. When technical debt is treated as a priority and paid down and architecture is continuously improved and modernized, teams can work with flow, delivering better value sooner, safer, and happier. And the business ultimately wins when developers can deliver on enterprise performance goals.

The Fourth Ideal: Psychological Safety

Psychological safety is one of the top predictors of team performance. When team members feel safe to talk about problems, problems can not only be fixed but prevented. Solving problems requires honesty, and honesty requires an absence of fear. In knowledge work, psychological safety should be treated with the same importance as physical safety is in manufacturing.

The Fifth Ideal: Customer Focus

Customer focus relates to the difference between core and context as defined by Geoffrey Moore. Core is what customers are willing and able to pay for, the bread and butter of your business. Context is what they don’t care about, what it took to get them that product, including all the backend systems of an organization like HR and marketing and development. It’s critical to look at these Context systems as essential, as mission critical, and fund them appropriately. Context should never kill core.

And a shorter version that’s less engineer focused from “DevOps: A Primer For The Business Leader”:

  • Locality and Simplicity: alleviate dependencies between teams and components.
  • Focus, Flow, and Joy: the smooth flow of work that enables focus and joy.
  • Improvement of Daily Work: continuously improve and pay down technical debt.
  • Psychological Safety: a top predictor of team performance; enables improvement.
  • Customer Focus: optimize for customer value, not for a role-based silo.

Newer posts Older posts