Skip to content
This repository has been archived by the owner on Sep 18, 2021. It is now read-only.

Commit

Permalink
Merge branch 'twoeight' of github.com:twitter/flockdb into twoeight
Browse files Browse the repository at this point in the history
  • Loading branch information
freels committed Feb 25, 2011
2 parents 637cb51 + 19309cd commit 1038cfb
Show file tree
Hide file tree
Showing 10 changed files with 209 additions and 161 deletions.
12 changes: 11 additions & 1 deletion src/main/scala/com/twitter/flockdb/Edge.scala
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -20,8 +20,18 @@ import com.twitter.util.Time
import com.twitter.flockdb.jobs.single._ import com.twitter.flockdb.jobs.single._
import com.twitter.gizzard.scheduler.{PrioritizingJobScheduler, JsonJob, Repairable} import com.twitter.gizzard.scheduler.{PrioritizingJobScheduler, JsonJob, Repairable}


case class Edge(sourceId: Long, destinationId: Long, position: Long, updatedAt: Time, count: Int, object Edge {
def apply(sourceId: Long, destinationId: Long, position: Long, updatedAt: Time, count: Int, state: State) = new Edge(sourceId, destinationId, position, updatedAt, count, state)
}

case class Edge(sourceId: Long, destinationId: Long, position: Long, updatedAtSeconds: Int, count: Int,
state: State) extends Ordered[Edge] with Repairable[Edge]{ state: State) extends Ordered[Edge] with Repairable[Edge]{

def this(sourceId: Long, destinationId: Long, position: Long, updatedAt: Time, count: Int, state: State) =
this(sourceId, destinationId, position, updatedAt.inSeconds, count, state)

val updatedAt = Time.fromSeconds(updatedAtSeconds)

def schedule(tableId: Int, forwardingManager: ForwardingManager, scheduler: PrioritizingJobScheduler[JsonJob], priority: Int) = { def schedule(tableId: Int, forwardingManager: ForwardingManager, scheduler: PrioritizingJobScheduler[JsonJob], priority: Int) = {
scheduler.put(priority, toJob(tableId, forwardingManager)) scheduler.put(priority, toJob(tableId, forwardingManager))
} }
Expand Down
17 changes: 16 additions & 1 deletion src/main/scala/com/twitter/flockdb/Metadata.scala
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -20,7 +20,22 @@ import com.twitter.util.Time
import com.twitter.gizzard.scheduler._ import com.twitter.gizzard.scheduler._
import jobs.multi._ import jobs.multi._


case class Metadata(sourceId: Long, state: State, count: Int, updatedAt: Time) extends Ordered[Metadata] with Repairable[Metadata] { object Metadata {
def apply(sourceId: Long, state: State, count: Int, updatedAt: Time) = new Metadata(sourceId, state, count, updatedAt)
def apply(sourceId: Long, state: State, updatedAt: Time) = new Metadata(sourceId, state, updatedAt)
}

case class Metadata(sourceId: Long, state: State, count: Int, updatedAtSeconds: Int) extends Ordered[Metadata] with Repairable[Metadata] {

def this(sourceId: Long, state: State, count: Int, updatedAt: Time) =
this(sourceId, state, count, updatedAt.inSeconds)

def this(sourceId: Long, state: State, updatedAt: Time) =
this(sourceId, state, 0, updatedAt.inSeconds)

val updatedAt = Time.fromSeconds(updatedAtSeconds)


def compare(other: Metadata) = { def compare(other: Metadata) = {
val out = updatedAt.compare(other.updatedAt) val out = updatedAt.compare(other.updatedAt)
if (out == 0) { if (out == 0) {
Expand Down
12 changes: 6 additions & 6 deletions src/main/scala/com/twitter/flockdb/shards/SqlShard.scala
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ class SqlShard(val queryEvaluator: QueryEvaluator, val shardInfo: shards.ShardIn


def getMetadata(sourceId: Long): Option[Metadata] = { def getMetadata(sourceId: Long): Option[Metadata] = {
queryEvaluator.selectOne("SELECT * FROM " + tablePrefix + "_metadata WHERE source_id = ?", sourceId) { row => queryEvaluator.selectOne("SELECT * FROM " + tablePrefix + "_metadata WHERE source_id = ?", sourceId) { row =>
Metadata(sourceId, State(row.getInt("state")), row.getInt("count"), Time.fromSeconds(row.getInt("updated_at"))) new Metadata(sourceId, State(row.getInt("state")), row.getInt("count"), Time.fromSeconds(row.getInt("updated_at")))
} }
} }


Expand All @@ -124,7 +124,7 @@ class SqlShard(val queryEvaluator: QueryEvaluator, val shardInfo: shards.ShardIn
queryEvaluator.select(SelectCopy, query, cursor.position, count + 1) { row => queryEvaluator.select(SelectCopy, query, cursor.position, count + 1) { row =>
if (i < count) { if (i < count) {
val sourceId = row.getLong("source_id") val sourceId = row.getLong("source_id")
metadatas += Metadata(sourceId, State(row.getInt("state")), row.getInt("count"), metadatas += new Metadata(sourceId, State(row.getInt("state")), row.getInt("count"),
Time.fromSeconds(row.getInt("updated_at"))) Time.fromSeconds(row.getInt("updated_at")))
nextCursor = Cursor(sourceId) nextCursor = Cursor(sourceId)
i += 1 i += 1
Expand Down Expand Up @@ -384,7 +384,7 @@ class SqlShard(val queryEvaluator: QueryEvaluator, val shardInfo: shards.ShardIn


private def updateEdge(transaction: Transaction, metadata: Metadata, edge: Edge, private def updateEdge(transaction: Transaction, metadata: Metadata, edge: Edge,
oldEdge: Edge): Int = { oldEdge: Edge): Int = {
if ((oldEdge.updatedAt == edge.updatedAt) && (oldEdge.state max edge.state) != edge.state) return 0 if ((oldEdge.updatedAtSeconds == edge.updatedAtSeconds) && (oldEdge.state max edge.state) != edge.state) return 0


val updatedRows = if ( val updatedRows = if (
oldEdge.state != Archived && // Only update position when coming from removed or negated into normal oldEdge.state != Archived && // Only update position when coming from removed or negated into normal
Expand Down Expand Up @@ -563,7 +563,7 @@ class SqlShard(val queryEvaluator: QueryEvaluator, val shardInfo: shards.ShardIn
queryEvaluator.transaction { transaction => queryEvaluator.transaction { transaction =>
transaction.selectOne(SelectModify, transaction.selectOne(SelectModify,
"SELECT * FROM " + tablePrefix + "_metadata WHERE source_id = ? FOR UPDATE", sourceId) { row => "SELECT * FROM " + tablePrefix + "_metadata WHERE source_id = ? FOR UPDATE", sourceId) { row =>
f(transaction, Metadata(sourceId, State(row.getInt("state")), row.getInt("count"), Time.fromSeconds(row.getInt("updated_at")))) f(transaction, new Metadata(sourceId, State(row.getInt("state")), row.getInt("count"), Time.fromSeconds(row.getInt("updated_at"))))
} getOrElse(throw new MissingMetadataRow) } getOrElse(throw new MissingMetadataRow)
} }
} catch { } catch {
Expand All @@ -579,7 +579,7 @@ class SqlShard(val queryEvaluator: QueryEvaluator, val shardInfo: shards.ShardIn
queryEvaluator.transaction { transaction => queryEvaluator.transaction { transaction =>
transaction.select(SelectModify, transaction.select(SelectModify,
"SELECT * FROM " + tablePrefix + "_metadata WHERE source_id in (?) FOR UPDATE", sourceIds) { row => "SELECT * FROM " + tablePrefix + "_metadata WHERE source_id in (?) FOR UPDATE", sourceIds) { row =>
metadataMap.put(row.getLong("source_id"), Metadata(row.getLong("source_id"), State(row.getInt("state")), row.getInt("count"), Time.fromSeconds(row.getInt("updated_at")))) metadataMap.put(row.getLong("source_id"), new Metadata(row.getLong("source_id"), State(row.getInt("state")), row.getInt("count"), Time.fromSeconds(row.getInt("updated_at"))))
} }
if (metadataMap.size < sourceIds.length) if (metadataMap.size < sourceIds.length)
throw new MissingMetadataRow throw new MissingMetadataRow
Expand Down Expand Up @@ -632,7 +632,7 @@ class SqlShard(val queryEvaluator: QueryEvaluator, val shardInfo: shards.ShardIn
// FIXME: computeCount could be really expensive. :( // FIXME: computeCount could be really expensive. :(
def updateMetadata(sourceId: Long, state: State, updatedAt: Time) { def updateMetadata(sourceId: Long, state: State, updatedAt: Time) {
atomically(sourceId) { (transaction, metadata) => atomically(sourceId) { (transaction, metadata) =>
if ((updatedAt != metadata.updatedAt) || ((metadata.state max state) == state)) { if ((updatedAt.inSeconds != metadata.updatedAtSeconds) || ((metadata.state max state) == state)) {
transaction.execute("UPDATE " + tablePrefix + "_metadata SET state = ?, updated_at = ?, count = ? WHERE source_id = ? AND updated_at <= ?", transaction.execute("UPDATE " + tablePrefix + "_metadata SET state = ?, updated_at = ?, count = ? WHERE source_id = ? AND updated_at <= ?",
state.id, updatedAt.inSeconds, computeCount(sourceId, state), sourceId, updatedAt.inSeconds) state.id, updatedAt.inSeconds, computeCount(sourceId, state), sourceId, updatedAt.inSeconds)
} }
Expand Down
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import java.io.File
import org.specs.Specification import org.specs.Specification
import com.twitter.gizzard.shards.{Busy, ShardId, ShardInfo} import com.twitter.gizzard.shards.{Busy, ShardId, ShardInfo}
import com.twitter.gizzard.nameserver.Forwarding import com.twitter.gizzard.nameserver.Forwarding
import com.twitter.gizzard.scheduler._
import com.twitter.gizzard.test.NameServerDatabase import com.twitter.gizzard.test.NameServerDatabase
import com.twitter.util.Eval import com.twitter.util.Eval
import com.twitter.querulous.evaluator.QueryEvaluatorFactory import com.twitter.querulous.evaluator.QueryEvaluatorFactory
Expand All @@ -46,6 +47,10 @@ abstract class ConfiguredSpecification extends Specification {
} }
} }
} }

def jsonMatching(list1: Iterable[JsonJob], list2: Iterable[JsonJob]) = {
list1 must eventually(verify(l1 => { l1.map(_.toJson).sameElements(list2.map(_.toJson))}))
}
} }


abstract class IntegrationSpecification extends ConfiguredSpecification with NameServerDatabase { abstract class IntegrationSpecification extends ConfiguredSpecification with NameServerDatabase {
Expand Down
173 changes: 81 additions & 92 deletions src/test/scala/com/twitter/flockdb/integration/EdgesSpec.scala
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -47,42 +47,37 @@ class EdgesSpec extends IntegrationSpecification {


"get_metadata" in { "get_metadata" in {
reset(config) reset(config)
Time.withCurrentTimeFrozen { time => flock.contains_metadata(alice, FOLLOWS) must eventually(be_==(false))
flock.contains_metadata(alice, FOLLOWS) must eventually(be_==(false)) flock.execute(Select(alice, FOLLOWS, bob).add.toThrift)
flock.execute(Select(alice, FOLLOWS, bob).add.toThrift) flock.contains_metadata(alice, FOLLOWS) must eventually(be_==(true))
flock.contains_metadata(alice, FOLLOWS) must eventually(be_==(true))

// updated_at should not be confused with created_at. Flock rows are commonly inserted with updated_at t=0.
// This is done to make their sort order low, and prevents a race condition in the case where in an empty db:
//
// 1. Mark alice archived.
// 2. Wait 1 second
// 3. Insert edge between alice and bob
// 4. Play those two operations in the db out of order.
// 5. Observe that alice is unfortunately still in the normal state.
//
flock.get_metadata(alice, FOLLOWS) must eventually (be_==(flockdb.Metadata(alice, State.Normal, 1, Time.epoch).toThrift))


} // updated_at should not be confused with created_at. Flock rows are commonly inserted with updated_at t=0.
// This is done to make their sort order low, and prevents a race condition in the case where in an empty db:
//
// 1. Mark alice archived.
// 2. Wait 1 second
// 3. Insert edge between alice and bob
// 4. Play those two operations in the db out of order.
// 5. Observe that alice is unfortunately still in the normal state.
//
flock.get_metadata(alice, FOLLOWS) must eventually (be_==(new flockdb.Metadata(alice, State.Normal, 1, Time.epoch).toThrift))
} }


"add" in { "add" in {
"existing graph" in { "existing graph" in {
reset(config) reset(config)
Time.withCurrentTimeFrozen { time => flock.execute(Select(alice, FOLLOWS, bob).add.toThrift)
flock.execute(Select(alice, FOLLOWS, bob).add.toThrift) val term = new QueryTerm(alice, FOLLOWS, true)
val term = new QueryTerm(alice, FOLLOWS, true) term.setDestination_ids(List[Long](bob).pack)
term.setDestination_ids(List[Long](bob).pack) term.setState_ids(List[Int](State.Normal.id).toJavaList)
term.setState_ids(List[Int](State.Normal.id).toJavaList) val op = new SelectOperation(SelectOperationType.SimpleQuery)
val op = new SelectOperation(SelectOperationType.SimpleQuery) op.setTerm(term)
op.setTerm(term) val page = new Page(1, Cursor.Start.position)
val page = new Page(1, Cursor.Start.position) flock.select(List(op).toJavaList, page).ids.array.size must eventually(be_>(0))
flock.select(List(op).toJavaList, page).ids.array.size must eventually(be_>(0)) Thread.sleep(1000)
time.advance(1.second) flock.execute(Select(alice, FOLLOWS, bob).remove.toThrift)
flock.execute(Select(alice, FOLLOWS, bob).remove.toThrift) flock.select(List(op).toJavaList, page).ids.array.size must eventually(be_==(0))
flock.select(List(op).toJavaList, page).ids.array.size must eventually(be_==(0)) flock.count(Select(alice, FOLLOWS, Nil).toThrift) mustEqual 0
flock.count(Select(alice, FOLLOWS, Nil).toThrift) mustEqual 0
}
} }


"nonexistent graph" in { "nonexistent graph" in {
Expand All @@ -94,43 +89,41 @@ class EdgesSpec extends IntegrationSpecification {
"remove" in { "remove" in {
reset(config) reset(config)
flock.execute(Select(bob, FOLLOWS, alice).remove.toThrift) flock.execute(Select(bob, FOLLOWS, alice).remove.toThrift)
(!flock.contains(bob, FOLLOWS, alice) && flock.contains(bob, FOLLOWS, alice) must eventually(beFalse)
flock.count(Select(alice, FOLLOWS, Nil).toThrift) == 0 && flock.count(Select(alice, FOLLOWS, Nil).toThrift) must eventually(be_==(0))
flock.count(Select(Nil, FOLLOWS, alice).toThrift) == 0) must eventually(beTrue) flock.count(Select(Nil, FOLLOWS, alice).toThrift) must eventually(be_==(0))
} }


"archive" in { "archive" in {
reset(config) reset(config)
Time.withCurrentTimeFrozen { time => flock.execute(Select(alice, FOLLOWS, bob).add.toThrift)
flock.execute(Select(alice, FOLLOWS, bob).add.toThrift) flock.execute(Select(alice, FOLLOWS, carl).add.toThrift)
flock.execute(Select(alice, FOLLOWS, carl).add.toThrift) flock.execute(Select(alice, FOLLOWS, darcy).add.toThrift)
flock.execute(Select(alice, FOLLOWS, darcy).add.toThrift) flock.execute(Select(darcy, FOLLOWS, alice).add.toThrift)
flock.execute(Select(darcy, FOLLOWS, alice).add.toThrift) flock.count(Select(alice, FOLLOWS, ()).toThrift) must eventually(be_==(3))
(flock.count(Select(alice, FOLLOWS, ()).toThrift) == 3 && flock.count(Select((), FOLLOWS, alice).toThrift) must eventually(be_==(1))
flock.count(Select((), FOLLOWS, alice).toThrift) == 1) must eventually(beTrue) for (destinationId <- List(bob, carl, darcy)) {
for (destinationId <- List(bob, carl, darcy)) { flock.count(Select((), FOLLOWS, destinationId).toThrift) must eventually(be_==(1))
flock.count(Select((), FOLLOWS, destinationId).toThrift) must eventually(be_==(1)) }
} flock.count(Select(darcy, FOLLOWS, ()).toThrift) must eventually(be_==(1))
flock.count(Select(darcy, FOLLOWS, ()).toThrift) must eventually(be_==(1))

Thread.sleep(1000)
time.advance(1.second) flock.execute((Select(alice, FOLLOWS, ()).archive + Select((), FOLLOWS, alice).archive).toThrift)
flock.execute((Select(alice, FOLLOWS, ()).archive + Select((), FOLLOWS, alice).archive).toThrift) flock.count(Select(alice, FOLLOWS, ()).toThrift) must eventually(be_==(0))
(flock.count(Select(alice, FOLLOWS, ()).toThrift) == 0 && flock.count(Select((), FOLLOWS, alice).toThrift) must eventually(be_==(0))
flock.count(Select((), FOLLOWS, alice).toThrift) == 0) must eventually(beTrue) for (destinationId <- List(bob, carl, darcy)) {
for (destinationId <- List(bob, carl, darcy)) { flock.count(Select((), FOLLOWS, destinationId).toThrift) must eventually(be_==(0))
flock.count(Select((), FOLLOWS, destinationId).toThrift) must eventually(be_==(0)) }
} flock.count(Select(darcy, FOLLOWS, ()).toThrift) must eventually(be_==(0))
flock.count(Select(darcy, FOLLOWS, ()).toThrift) must eventually(be_==(0))

Thread.sleep(1000)
time.advance(1.seconds) flock.execute((Select(alice, FOLLOWS, ()).add + Select((), FOLLOWS, alice).add).toThrift)
flock.execute((Select(alice, FOLLOWS, ()).add + Select((), FOLLOWS, alice).add).toThrift) flock.count(Select(alice, FOLLOWS, ()).toThrift) must eventually(be_==(3))
(flock.count(Select(alice, FOLLOWS, ()).toThrift) == 3 && flock.count(Select((), FOLLOWS, alice).toThrift) must eventually(be_==(1))
flock.count(Select((), FOLLOWS, alice).toThrift) == 1) must eventually(beTrue) for (destinationId <- List(bob, carl, darcy)) {
for (destinationId <- List(bob, carl, darcy)) { flock.count(Select((), FOLLOWS, destinationId).toThrift) must eventually(be_==(1))
flock.count(Select((), FOLLOWS, destinationId).toThrift) must eventually(be_==(1))
}
flock.count(Select(darcy, FOLLOWS, ()).toThrift) must eventually(be_==(1))
} }
flock.count(Select(darcy, FOLLOWS, ()).toThrift) must eventually(be_==(1))
} }


"archive & unarchive concurrently" in { "archive & unarchive concurrently" in {
Expand Down Expand Up @@ -158,20 +151,18 @@ class EdgesSpec extends IntegrationSpecification {


"toggle polarity" in { "toggle polarity" in {
reset(config) reset(config)
Time.withCurrentTimeFrozen { time => flock.execute(Select(alice, FOLLOWS, bob).add.toThrift)
flock.execute(Select(alice, FOLLOWS, bob).add.toThrift) flock.execute(Select(alice, FOLLOWS, carl).add.toThrift)
flock.execute(Select(alice, FOLLOWS, carl).add.toThrift) flock.execute(Select(alice, FOLLOWS, darcy).add.toThrift)
flock.execute(Select(alice, FOLLOWS, darcy).add.toThrift) flock.count(Select(alice, FOLLOWS, ()).toThrift) must eventually(be_==(3))
flock.count(Select(alice, FOLLOWS, ()).toThrift) must eventually(be_==(3)) Thread.sleep(1000)
time.advance(1.second) flock.execute(Select(alice, FOLLOWS, ()).negate.toThrift)
flock.execute(Select(alice, FOLLOWS, ()).negate.toThrift) flock.count(Select(alice, FOLLOWS, ()).toThrift) must eventually(be_==(0))
flock.count(Select(alice, FOLLOWS, ()).toThrift) must eventually(be_==(0)) flock.count(Select(alice, FOLLOWS, ()).negative.toThrift) must eventually(be_==(3))
flock.count(Select(alice, FOLLOWS, ()).negative.toThrift) must eventually(be_==(3)) Thread.sleep(1000)
time.advance(1.second) flock.execute(Select(alice, FOLLOWS, ()).add.toThrift)
flock.execute(Select(alice, FOLLOWS, ()).add.toThrift) flock.count(Select(alice, FOLLOWS, ()).toThrift) must eventually(be_==(3))
flock.count(Select(alice, FOLLOWS, ()).toThrift) must eventually(be_==(3)) flock.count(Select(alice, FOLLOWS, ()).negative.toThrift) must eventually(be_==(0))
flock.count(Select(alice, FOLLOWS, ()).negative.toThrift) must eventually(be_==(0))
}
} }


"counts" in { "counts" in {
Expand All @@ -188,22 +179,20 @@ class EdgesSpec extends IntegrationSpecification {
"select_edges" in { "select_edges" in {
"simple query" in { "simple query" in {
reset(config) reset(config)
Time.withCurrentTimeFrozen { time => flock.execute(Select(alice, FOLLOWS, bob).add.toThrift)
flock.execute(Select(alice, FOLLOWS, bob).add.toThrift) Thread.sleep(1000)
time.advance(1.second) flock.execute(Select(alice, FOLLOWS, carl).add.toThrift)
flock.execute(Select(alice, FOLLOWS, carl).add.toThrift) flock.count(Select(alice, FOLLOWS, ()).toThrift) must eventually(be_==(2))
flock.count(Select(alice, FOLLOWS, ()).toThrift) must eventually(be_==(2))

val term = new QueryTerm(alice, FOLLOWS, true)
val term = new QueryTerm(alice, FOLLOWS, true) term.setState_ids(List[Int](State.Normal.id).toJavaList)
term.setState_ids(List[Int](State.Normal.id).toJavaList) val query = new EdgeQuery(term, new Page(10, Cursor.Start.position))
val query = new EdgeQuery(term, new Page(10, Cursor.Start.position)) val resultsList = flock.select_edges(List[EdgeQuery](query).toJavaList).toList
val resultsList = flock.select_edges(List[EdgeQuery](query).toJavaList).toList resultsList.size mustEqual 1
resultsList.size mustEqual 1 val results = resultsList(0)
val results = resultsList(0) results.next_cursor mustEqual Cursor.End.position
results.next_cursor mustEqual Cursor.End.position results.prev_cursor mustEqual Cursor.End.position
results.prev_cursor mustEqual Cursor.End.position results.edges.toList.map { _.destination_id }.toList mustEqual List[Long](carl, bob)
results.edges.toList.map { _.destination_id }.toList mustEqual List[Long](carl, bob)
}
} }


"intersection" in { "intersection" in {
Expand Down
8 changes: 4 additions & 4 deletions src/test/scala/com/twitter/flockdb/unit/EdgeSpec.scala
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -32,21 +32,21 @@ object EdgeSpec extends ConfiguredSpecification with JMocker with ClassMocker {


"Edge" should { "Edge" should {
"normal becomes single.Add" in { "normal becomes single.Add" in {
val edge = Edge(source, dest, pos, now, count, State.Normal) val edge = new Edge(source, dest, pos, now, count, State.Normal)
edge.toJob(graph, forwardingManager) mustEqual new Add(source, graph, dest, pos, now, forwardingManager, OrderedUuidGenerator) edge.toJob(graph, forwardingManager) mustEqual new Add(source, graph, dest, pos, now, forwardingManager, OrderedUuidGenerator)
} }


"removed becomes single.Remove" in { "removed becomes single.Remove" in {
val edge = Edge(source, dest, pos, now, count, State.Removed) val edge = new Edge(source, dest, pos, now, count, State.Removed)
edge.toJob(graph, forwardingManager) mustEqual new Remove(source, graph, dest, pos, now, forwardingManager, OrderedUuidGenerator) edge.toJob(graph, forwardingManager) mustEqual new Remove(source, graph, dest, pos, now, forwardingManager, OrderedUuidGenerator)
} }


"archived becomes single.Archive" in { "archived becomes single.Archive" in {
val edge = Edge(source, dest, pos, now, count, State.Archived) val edge = new Edge(source, dest, pos, now, count, State.Archived)
edge.toJob(graph, forwardingManager) mustEqual new Archive(source, graph, dest, pos, now, forwardingManager, OrderedUuidGenerator) edge.toJob(graph, forwardingManager) mustEqual new Archive(source, graph, dest, pos, now, forwardingManager, OrderedUuidGenerator)
} }
"negative becomes single.Negate" in { "negative becomes single.Negate" in {
val edge = Edge(source, dest, pos, now, count, State.Negative) val edge = new Edge(source, dest, pos, now, count, State.Negative)
edge.toJob(graph, forwardingManager) mustEqual new Negate(source, graph, dest, pos, now, forwardingManager, OrderedUuidGenerator) edge.toJob(graph, forwardingManager) mustEqual new Negate(source, graph, dest, pos, now, forwardingManager, OrderedUuidGenerator)
} }


Expand Down
Loading

0 comments on commit 1038cfb

Please sign in to comment.