Send email asynchroniously using Sidekiq.
Create your mailer us usual:
In this gist I would like to describe an idea for GraphQL subscriptions. It was inspired by conversations about subscriptions in the GraphQL slack channel and different GH issues, like #89 and #411.
At the moment GraphQL allows 2 types of queries:
query
mutation
Reference implementation also adds the third type: subscription
. It does not have any semantics yet, so here I would like to propose one possible semantics interpretation and the reasoning behind it.
All of the below properties or methods, when requested/called in JavaScript, will trigger the browser to synchronously calculate the style and layout*. This is also called reflow or layout thrashing, and is common performance bottleneck.
Generally, all APIs that synchronously provide layout metrics will trigger forced reflow / layout. Read on for additional cases and details.
elem.offsetLeft
, elem.offsetTop
, elem.offsetWidth
, elem.offsetHeight
, elem.offsetParent
Tether is a great library for positioning stuff (tooltips, modals, hints, etc) in your web app.
But, as I use React, it was pretty problematic for me, as Tether mutates the DOM and React breaks miserably when it sees mutated DOM. The solution is to have the tethered element outside the part of the DOM tree which is controlled by React (in this case, I use document.body
).
That's why I created 2 helpers to use Tether with React.
The first one, TetheredElement
is a plain JS helper to create a new element, attach it to some other one via Tether, and populate it with some React component.
The second one, TetherTarget
is a React component and it uses TetheredElement
to integrate it further with React, so that you can attach components to each other with Tether, without leaving the cozy React/JSX world and worrying about manual DOM operations. Just write:
The MIT License (MIT) | |
Copyright (c) 2015 Justin Perry | |
Permission is hereby granted, free of charge, to any person obtaining a copy of | |
this software and associated documentation files (the "Software"), to deal in | |
the Software without restriction, including without limitation the rights to | |
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of | |
the Software, and to permit persons to whom the Software is furnished to do so, | |
subject to the following conditions: |
Uploads large files in multiple chunks. Also has the ability to resume if the upload is interrupted.
Typical usage:
/upload
with the first chunk of the file and receive an upload id in return.POST /upload/commit/:id
:
import { Component } from "React"; | |
export var Enhance = ComposedComponent => class extends Component { | |
constructor() { | |
this.state = { data: null }; | |
} | |
componentDidMount() { | |
this.setState({ data: 'Hello' }); | |
} | |
render() { |
Inspired or reignited by BEM and Sass 3.4, I’ve been exploring new ways to write clean, object oriented CSS.
If you have not already introduced yourselves to either Sass or BEM, I highly recommend reading getting your head ’round BEM syntax and Sass 3.4 is Out!.
I love the idea of object oriented CSS. It’s all about modular, longer-lasting code that’s easier to edit. It promises less headaches when I come back to the code days, weeks, or months later. Still, two issues primarily haunt me, and I’ll be frank about them:
My largest Sidekiq application had a memory leak and I was able to find and fix it in just few hours spent on analyzing Ruby's heap. In this post I'll show my profiling setup.
As you might know Ruby 2.1 introduced a few great changes to ObjectSpace, so now it's much easier to find a line of code that is allocating too many objects. Here is great post explaining how it's working.
I was too lazy to set up some seeding and run it locally, so I checked that test suite passes when profiling is enabled and pushed debugging to production. Production environment also suited me better since my jobs data can't be fully random generated.
So, in order to profile your worker, add this to your Sidekiq configuration:
if ENV["PROFILE"]