2

我正在 Clojure 中围绕 OrientDB 构建一个包装器。OrientDB 的最大限制之一(恕我直言)ODatabaseDocumentTx是不是线程安全的,但是这个东西的生命周期.open()应该.close()代表单个事务,有效地强制事务发生是单个线程。事实上,这些混合数据库/事务对象的线程本地引用是默认提供的。但是,如果我想登录与保持“真实”状态相同的线程怎么办?如果我遇到错误,日志条目也会回滚!仅这个用例就让我远离了几乎所有 DBMS,因为大多数 DBMS 不允许命名事务范围管理。/肥皂盒

无论如何,OrientDB 就是这样,对我来说不会改变。我正在使用 Clojure,我想要一种优雅的方式来构造一个with-tx宏,以便对正文中的所有命令式数据库调用with-tx进行序列化。

with-tx显然,我可以通过在生成的主体的顶层创建一个哨兵并将每个表单解构到最低层并将它们包装在一个同步块中来强制它。这太可怕了,我不确定它会如何与pmap.

我可以在宏主体中搜索对ODatabaseDocumentTx对象的调用并将它们包装在同步块中。

我想我可以用代理创建某种调度系统。

或者我可以使用同步方法调用子类化 ODatabaseDocumentTx。

我正在挠头,试图想出其他方法。想法?一般来说,代理方法似乎更有吸引力,因为如果一个代码块散布有数据库方法调用,我宁愿预先完成所有计算,对调用进行排队,最后只向数据库发送一大堆东西。然而,这假设计算不需要确保读取的一致性。身份证。

4

2 回答 2

1

听起来像是Lamina的工作。

于 2013-05-01T04:25:58.580 回答
0

一种选择是在线程池中使用 Executor 和 1 个线程。如下所示。您可以围绕这个概念创建一个很好的宏。

(import 'java.util.concurrent.Executors)
(import 'java.util.concurrent.Callable)

(defmacro sync [executor & body]
  `(.get (.submit ~executor (proxy [Callable] []
                             (call []
                               (do ~@body))))))

(let [exe (Executors/newFixedThreadPool (int 1))
      dbtx (sync exe (DatabaseTx.))]
  (do
    (sync exe (readfrom dbtx))
    (sync exe (writeto dbtx))))

sync宏确保主体表达式在执行器(只有一个线程)中执行,并等待操作完成,以便所有操作一一执行。

于 2013-05-01T05:15:28.710 回答