Escribir solo una función que guarda objetos dados en sqlite

Solo estoy comenzando con clojure y estoy atascado pensando cómo implementar una funcionalidad aparentemente sencilla.

Hay una función generator, que toma (entre otros) un saver funcionar como un argumento. los generator hace todo tipo de cosas y genera ciertos objetos de datos con regularidad, que deben guardarse. Se supone que este ahorro lo maneja el saver función, y así el generator llama al saver con los datos que deben guardarse, cada vez que se generan datos.

Ahora, una función de ahorro que debo escribir es una que guarda los datos en una base de datos sqlite. ¿Cómo debo hacer esto?

  • Una estrategia en la que pensé es crear una conexión a la base de datos sqlite en el saver función. Cree una nueva conexión cada vez que se vayan a guardar datos, guarde los datos (solo una fila en una tabla) y cierre la conexión. Esto parecía un poco ineficaz. Especialmente considerando que los datos se generan cada 2-5 segundos.

  • Otra idea es mantener una conexión abierta como una var a nivel de módulo, que se establece en nil al principio. La conexión se abre la primera vez que saver Se llama a la función y se reutiliza en las siguientes llamadas. Esto parece que probablemente sería más eficiente, pero que yo sepa, requeriría un def forma dentro de la saver función. Personalmente, no disfruto haciendo eso.

  • Otro (¿loco?) Pensamiento que tuve fue usar un agente que guarde el objeto de conexión, inicialmente configurado como nil. El saver será una función que sends datos al agente. El agente crea la conexión la primera vez que la necesita y la guarda en su objeto de datos asociado. Esto parece funcionar bien, pero los agentes no están diseñados para esto, ¿verdad?

Entonces, ¿cómo abordan el problema? ¿Existe algún otro paradigma adecuado solo para este caso? ¿O debería hacer una de las anteriores?

PD. Pasé mucho tiempo escribiendo esto, ya que es muy difícil expresar mi problema con palabras. No estoy seguro de haberlo hecho bien. Avísame si algo no está claro.

preguntado el 27 de agosto de 11 a las 16:08

¿Tiene alguna idea de cómo se cerraría la conexión? ¿O eso no es importante, simplemente puede seguir comprometiéndose? -

No es que importante para mí en este momento, pero estoy dispuesto a creer que el jvm lo cierra con elegancia cuando mi aplicación se cierra de todos modos. Además, necesitaré la conexión durante toda la vida de la aplicación. -

No creo que pueda resolver su problema con una forma de definición dentro de una función. Una forma def define un enlace inmutable, independientemente de dónde se defina. No puede usar una def para decir, "si este valor es nulo, establézcalo en algo que no sea nulo, de lo contrario use el valor actual". -

Que yo sepa, no existe tal cosa como un unión inmutable. Usted enlatado def y redef a var tantas veces como quieras, aunque se desaconseja. Lo que se vincula a una variable es no lo inmutable, el objeto mismo que se crea es lo inmutable. También, def la forma funciona dentro de una función, ideone.com/YTiOI . Por supuesto, me gustaría que alguien mejor en clojure confirmara lo que dije :) -

1 Respuestas

su segunda solución suena mejor. si no quieres usar un mutable Var (creado a través de def), entonces podría crear la conexión en una función de "fábrica" ​​como un valor simple inmutable (por lo que simplemente se lleva en el cierre):

(defn sqlite-saver-factory [path]
  (let [db-connection (open-sqlite-connection path)]
    (fn [data]
      (save-to-sqlite db-connection data))))
...
(generator (sqlite-saver-factory path) ...)

descargo de responsabilidad: no soy un gran experto en clojure; lo anterior es cómo haría esto en prácticamente cualquier lenguaje funcional. así que quizás haya un enfoque clojure más idiomático.

Respondido 27 ago 11, 21:08

cierres. Ahora, ¿por qué no pensé en eso? Esto es brillante. Solo la solución que necesito. Pero como dijiste, estoy dispuesto a ver un enfoque al estilo clojure, si es que es diferente. +1. - Shrikant Sharat

Un cierre es lo que hubiera recomendado si nadie me hubiera adelantado. Aunque usar un agente para serializar sus escrituras podría ser algo bueno para combinar esto, si no le importa dejar que sucedan en segundo plano. - amalloy

Sí, estoy de acuerdo con que suceda en segundo plano. Pero este caso de uso de agent no implica ninguna mutación en el objeto de datos del agente. Entonces, siento que los agentes son exagerados para lo que quiero lograr. - Shrikant Sharat

Sin embargo, me gusta la perspectiva de dejar que suceda en segundo plano. Igual que (.start (Thread. saver-fn)), ¿O hay un mejor camino? - Shrikant Sharat

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.