Skip to content

Instantly share code, notes, and snippets.

Persisted Sidekiq

Sidekiq is a Redis-backed Ruby library for creating background jobs.

Obviously, Redis is in memory. Since our tasks are very important, we cannot tolerate "missing" jobs as a consequence of Redis failures (such as sudden shutdown due to electricity issues and so on).

Your task is to create PersistedSidekiq, Redis-backed with DB fallback library for creating background jobs.

Requirements

  1. PersistedSidekiq should use Sidekiq internally.
// Java
public boolean isEmpty(String s) {
  return s.length() == 0;
}
# ruby
def empty?(s)
const request = require('request-promise-native');
const namespace = require('./node-request-context').getNamespace('some-namespace');
class SomeResource {
get() {
console.log(namespace.get('tid'));
return request('http://www.google.com').then((res) => {
// index.js
const http = require('http');
const uuid = require('uuid');
const SomeResource = require('./some_resource');
const namespace = require('./node-request-context').createNamespace('some-namespace');
http.createServer(function (req, res) {
namespace.run(() => {
const transactionId = uuid.v1();
console.log('Setting a new transaction id => ', transactionId);
namespace.set('tid', transactionId);
// node-request-context/index.js
const asyncHooks = require('async_hooks');
function createHooks(namespace) {
function init(asyncId, type, triggerId, resource) {
// Check if trigger has context
// Or in other words, check if tigger is part of any request
if (namespace.context[triggerId]) {
// Here we keep passing the context from
// the triggerId to the new asyncId
// node-request-context/index.js
const Namespace = require('./namespace');
const namespaces = {};
function createNamespace(name) {
if (namespaces[name]) { throw new Error(`A namespace for ${name} is already exists`); }
const namespace = new Namespace();
namespaces[name] = namespace;
createHooks(namespace); // wait for explanation below
// node-request-context/namespace.js
const asyncHooks = require('async_hooks');
class Namespace {
constructor() {
this.context = {};
}
run(fn) {
Calling setTimeout: execution: 1
Init Timeout resource: asyncId: 6 trigger: 1
Init TIMERWRAP resource: asyncId: 7 trigger: 1
Inside setTimeout: execution: 6
Destroy resource: execution: 0 asyncId: 6
Destroy resource: execution: 0 asyncId: 7
const fs = require('fs');
const async_hooks = require('async_hooks');
async_hooks.createHook({
init(asyncId, type, triggerAsyncId) {
fs.writeSync(1, `Init ${type} resource: asyncId: ${asyncId} trigger: ${triggerAsyncId}\n`);
},
destroy(asyncId) {
const eid = async_hooks.executionAsyncId();
fs.writeSync(1, `Destroy resource: execution: ${eid} asyncId: ${asyncId}\n`);
}
// First we define callbacks
const asyncHook = async_hooks.createHook({ init, before, after, destroy, promiseResolve });
// Then we enable the hooks
asyncHook.enable();