Archive

Coding Bits

I’m having a real “time is circular” moment.

It’s been almost 8 years since I wrote Python scripts to create stuffed animals using 3D models from video games. Now that I’m getting back into sewing, I’m discovering a whole new world of software for pattern makers.

CLO3D is the industry standard, offering advanced cloth simulations.

Valentina is the best open source alternative (GPL3!).

With FOSS tools, some are just as amazing as their non-FOSS counterparts while others are a little lacking. For example, I think Blender is entirely able to replace Maya and 3DS Max for a hobbyist animator. The same is true for Krita replacing Photoshop for illustrators. OpenSCAD and FreeCAD are not quite able to replace Solidworks for engineers.

I have very limited pattern making experience so I’m not a great judge for pattern making software. If cloth simulation is critical, then Valentina needs a lot more features to be able to compete with CLO3D. If cloth simulation isn’t super necessary, maybe Valentina would make an adequate substitute.

Either way, I’m loving learning about the ecosystem around sewing and making clothes. Sewing is a craft that dates back to ancient days and has neat jargon (like armscye). At the same time it’s been really modernized with the industrial clothing supply chain. It also has a fascinating digital component, like the transformation from flat pattern making to pattern making software.

It’s so cool!

Suppose you had sales table with timestamp and customer_id as the columns.

id timestamp customer_id
1 2011-03-17 10:31:01 7
2 2011-03-17 10:45:05 8
3 2011-03-17 10:47:05 7
4 2011-03-17 10:50:10 8

You want to query for what’s the average time between purchases for each customer.

You can use:

SELECT t.customer_id,
       AVG(t.difference) as interval
FROM ( 
  SELECT customer_id,
         timestamp - lag(timestamp) OVER (PARTITION BY customer_id ORDER BY timestamp) AS difference
  FROM sales
) t
GROUP BY t.customer_id

You’ll get:

customer_id interval
7 00:16:04
8 00:05:05

Sources:

There are a lot of ways to do this, but I searched for the title of this post and got few results.

One solution is to write some custom middleware. (WARNING: if you’re using Puma, make sure your middleware is threadsafe).

Here’s a great guide: https://lmiller1990.github.io/electic/posts/custom_middleware_in_rails_5.html

You can specify different behavior based on status codes:

  def call(env)
    @status, @headers, @body = @app.call(env)
    if @status == 400
      # do something here
    end
    [@status, @headers, @body]
  end

And you’ll need to add your middleware to the configs:

# config/environments/development.rb
config.middleware.insert_before ActionDispatch::ShowExceptions, MyMiddleware

Suppose you’re building a Rails app for Users who attend many Events, such that a User has_many :events. Now, suppose you want to query for all the Users who have attended an Event that occurred within the last week.

One simple way would be to fetch all the Events and, through those, grab all the Users that attended them, but this wouldn’t work well if we wanted to associate more complex filtering with Users, or use more complex joins.

When you’ve got a problem like that, this article by Richard Jones is phenomenal! I’ve needed to do this at two jobs and have a hard time dredging up this article, so I’m linking it here.

The gist is to use scenic to create and manage database views:

CREATE VIEW newest_events AS
  SELECT DISTINCT ON (user_id) *
  FROM events
  ORDER BY user_id, created_at DESC

Recently, we’ve been talking a lot about video games with our friends. It reminded me 11 years ago I made a game for the Nintendo DS Lite.

I don’t have any of the assets anymore except for these two screenshots:

title screen

game screen

It was neat to learn about all DS Lite hardware and thinking about processors and CPUs. Reminds me a little of Android development.

This post could also be titled “How to Set Up a Load Balancer in Front of Heroku” or “How to Set Up a Static IP Address on Heroku Without Add-ons.”

I work in East Africa, and data is fairly expensive for our users. A lot of telcos provide zero-ratings so that the owners of the service can choose to pay for the cost of the data instead of the users.

Zero-rating deals are typically scoped to a given IP address instead of a URL. If a service provider hosts a site onexample.com, which points to 12.34.56.78, they’ll need to arrange a zero-rating deal for 12.34.56.78.

We’re launching a new Web service on Heroku. I’d like to route traffic from a domain through to Heroku. Normally I’d follow Heroku’s Custom Domain Name guide, but because we’re providing zero-ratings I’ll need the client to interact with a specific IP address instead. My DNS needs to point to that specific IP address instead of to a Heroku subdomain.

I’m relatively new to networking, but after stumbling around for a while here’s what I set up.

I’m using HAProxy as a load balancer running on the server with the designated IP address. I set up SSL bridging following the HAproxy infrastructure layout guide.

haproxy_tls_bridging

The client accesses example.com, which resolves to the HAProxy server. The proxy forwards the request to Heroku, receives the response, and sends it back to the client.

Here are some specific configuration details:

  1. Create an A record in DNS pointing from your domain to the HAProxy server, which has your designated zero-rated IP address.

  2. Specify the HAProxy back-end to point to your app’s subdomain on Heroku:

  server MY-APP MY-APP.herokuapp.com ssl check cookie MY-APP.example.com sni req.hdr(Host)
  1. Meanwhile, on Heroku’s side, associate your subdomain with the app:
$ heroku domains:add MY-APP.example.com

And you’re done!

While debugging this system I noticed that my application code was issuing 301 Redirect responses when I hit MY-APP.example.com, sending me to MY-APP.herokuapp.com. I initially thought that this was a result of mis-configuring something, but it turned out that those redirects were being issued from application logic, not by HAProxy or Heroku (which doesn’t perform redirects).

Aside from that brief redirection confusion, this configuration has worked pretty well! It might also be useful if you’d like more fine-grained control when setting up your static IP address than you’d get from a paid Heroku add-on like QuotaStatic or Fixie.

An alternative implementation: It’s also possible to set up SSL pass-through. However, that requires giving your SSL certs to Heroku. Since I already had an ACM (automated certificate management) system, I wouldn’t have been able to auto-renew those certs on Heroku. And since I also already had a working HAProxy instance to build on, manually renewing certs for Heroku seemed more complicated than the solution presented above.

For a long time, I’d thought GIMP had bad support for tablets. Aside from feeling a lot of kinetic dissonance from the choppy feedback, I saw multiple mouse cursors. One cursor was from my laptop touch pad and another from my Wacom stylus. The two moved independently and stylus cursor disappeared every time I navigated away from the canvas.

double-cursor

I searched a lot for GIMP tablet configurations and Wacom drivers for Linux, but turns out it was a Wayland issue.

Gnome with Xorg solved everything!

Hope this helps whoever else stumbles across this.