anchor.diff:      [<MaxLength(Int32.MaxValue)>]
       member val EventJson = "" with get, set
   
  -SQLite3.Config (SQLite3.ConfigOption.Serialized) |> ignore
  -
  -let db () =
  -    new SQLiteConnection(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Personal), "db"))
  +let db = new SQLiteConnection(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Personal), "db"))
  +let write computation =  
  +    lock db (fun _ -> computation db) 
   
   let init () =
  -    use db = db ()
       db.CreateTable<ChatHistory> () |> ignore
       db.CreateTable<ChatHistoryEvent> () |> ignore
       db.CreateTable<Error> () |> ignore
  
positive.code:     #endif
  
  let clearErrors () =
      use db = db ()
      let errors = db.Table<Error>().ToList()
      for error in errors.Take(100) do
          db.Delete(error) |> ignore
  
  let createChatHistoryEvent (entity:Entity) historyType eventJson =
      use db = db ()
      db.Insert
          (ChatHistoryEvent(
              EntityId = entity.Id,
              Type = historyType,
              EventJson = eventJson
          )) 
      |> ignore
  
      let count = db.Table<ChatHistoryEvent>().Count()
      if count > 500 then
          let toClear = db.Table<ChatHistoryEvent>().OrderBy(fun s -> s.LastStamp).Take(100).ToList()
  
          //TODO batch this
          for event in toClear do
              db.Delete(event) |> ignore
  
  let createChatHistory = 
      let processor = MailboxProcessor<(Entity * ChatHistoryType * (string * bool) option) * AsyncReplyChannel<unit>>.Start(fun inbox ->
          let rec loop () = async {
              let! (entity, historyType, last), channel = inbox.Receive()
              use db = db ()
              let existing = db.Table<ChatHistory>().Where(fun x -> x.EntityId = entity.Id).FirstOrDefault()
  
              match existing with
              | null -> 
                  db.Insert
                      (ChatHistory(
                          EntityId = entity.Id,
                          Label = entity.Label,
  
                          Slug = entity.Slug,
                          Image = entity.Image,
                          Last = "",
                          Read = true,
                          Type = historyType
                      )) 
                  |> ignore
  
              | existing -> 
                  match last with
  
negative.code:     fun message -> processor.PostAndAsyncReply(fun replyChannel -> message, replyChannel)
  
  let fetchChatHistoryById (id) =
      db.Table<ChatHistory>().Where(fun x -> x.EntityId = id).FirstOrDefault()
  
  let updateChatHistoryReadById (id) =
      let history = fetchChatHistoryById id
      match history with
      | null -> ()
      | history ->
          history.Read <- true
          write (fun db -> db.Update history |> ignore)
  
  let fetchChatHistoryUnreadCount () =
      db.Table<ChatHistory>().Where(fun s -> s.Read = false).Count()
  
  let fetchChatHistory () = 
      db.Table<ChatHistory>().OrderByDescending(fun s -> s.LastStamp).Take(100).ToList() 
  
  let fetchChatEventHistoryByEntity entityId =
      db.Table<ChatHistoryEvent>().Where(fun e -> e.EntityId = entityId).OrderByDescending(fun s -> s.LastStamp).Take(100).ToList() 
  
  let removeChatHistoryById (id) =
      let history = fetchChatHistoryById id
      write (fun db -> db.Delete(history) |> ignore)
  