Skip to content

Instantly share code, notes, and snippets.

@nkallen
nkallen / gist:787081
Created January 19, 2011 23:08
Some scatter/gather timeout idioms
/**
* The following code represents the "best effort" idiom, where N parallel requests are made
* and for those that fail to return within a global timeout, we use a default value.
*
* Below are three implementations of the same idiom. The building blocks are CountDown latches,
* which are a kind of barrier, and Timer threads. I'm not sure which is best.
*/
"Weaver" should {
"weave" in {
var timer: JavaTimer = null
import java.util.concurrent.atomic.AtomicReference
class Serializer {
abstract case class State {
def +(other: Unit => Unit): State
}
case object Idle extends State {
def +(other: Unit => Unit) = Working(List(other))
}
case class Working(items: Seq[Unit => Unit]) extends State {
class NotifyingFuture[A] extends Future[A] {
import NotifyingFuture._
private var result: Option[A] = None
private val computations = new ArrayBuffer[A => Unit]
def setResult(result: A) {
setResultIfEmpty(result) || {
throw new ImmutableResult("Result set multiple times: " + result)
}
@nkallen
nkallen / gist:316595
Created February 27, 2010 09:08
This is a prototype of a technique for testing distributed race conditions.
/*
This is a prototype of a technique for testing distributed race conditions.
Here is an example,
Suppose we have a command that performs an operation across two or more components.
And suppose more than one of these commands is run in parallel (across processes).
The race conditions will occur as each command process independently invokes methods
on these components in various orders.
import scala.collection.mutable._
// I want these std functions to be implicit:
implicit def tupled[a1, a2, b] = Function.tupled[a1, a2, b](_)
implicit def untupled[a1, a2, b] = Function.untupled[a1, a2, b](_)
class Connection
class ConnectionPool(size: Int) {
def withConnection[A](f: Connection => A) = f(new Connection)
trait Query { def i: Int }
// A Query and a Query Decorator
case class SimpleQuery(val i: Int) extends Query
case class TimingOutQuery(timeout: Int)(query: Query) extends Query { def i = query.i }
// Factories
type QueryFactory = Int => Query
// A thing that needs to make Queries

2010 Modularity Olympics

This is a contest, open to programming languages from all nations, to write modular and extensible code to solve the following problem: Implement a service that can run queries on a database.

The Challenge

Sounds simple right? Wrong! A programmer without control over the source-code of that service must be able to later add enhancements such as statistics collecting, timeouts, memoization, and so forth. There are a few more requirements:

  1. the “enhancements” must be specified in a configuration object which is consumed at run-time (e.g., it could be based on user-input).
  2. The enhancements are ordered (stats collecting wraps timeouts, not the other way around) but it must be possible to reverse the order of the enhancements at run-time.
  3. The enhancements must be “surgical” and not “global”. That is, it must be possible to simultaneously have two query services, one reversed and one not reversed, and even have a query service without any enhancements.
nkallen_: nkallen_: anyway, i want to stress that we basically agree about things so i want to be sure that the tone of the blog post is such
[7:25pm] nkallen_: [7:17pm] nkallen_: i would argue that what you do in rails 3 (according to these tweets I've read)
[7:25pm] nkallen_: [7:17pm] nkallen_: is exactly what I propose... this is just how one might do it in Ruby
[7:25pm] nkallen_: [7:18pm] nkallen_: but my point is conceptual and not about ruby
[7:25pm] nkallen_: [7:18pm] nkallen_: it applies to every oo language and also I might argue to functional languages
[7:25pm] nkallen_: [7:18pm] nkallen_: which is to structure a program around the ability to layer on enhanced functionality and ensure that no assumptions are hardcoded by abstracting over the manufacture of objects
[7:25pm] nkallen_: [7:19pm] nkallen_: in the literature, these techniques are called DI, decorators, and factories.
[7:25pm] nkallen_: [7:20pm] nkallen_: i like these terms because they reflect the concepts that are at work. because ruby m
/* This is when a refactoring really pays off.
*
* In order to make your code more modular, avoid hard-coding assumptions (or refactor them away).
* The most fundamental, anti-modular assumption in Object-Oriented software is the concrete type of objects.
* Any time you write "new MyClass" in your code (or in Ruby MyClass.new) you've hardcoded
* an assumption about the concrete class of the object you're allocating. These makes it impossible, for example,
* for someone to later add logging around method invocations of that object, or timeouts, or whatever.
*
* In a very dynamic language like Ruby, open classes and method aliasing mitigate this problem, but
* they don't solve it. If you manipulate a class to add logging, all instances of that class will have
# This comes from GenericWebLibrary
class BaseComponent
end
# This comes from RestExtensionLibrary
class RestComponent < BaseComponent
end
# In a language with mixins you could do
class SomeFilterStuff