/// <summary> /// Execute executes queries that return no rows, but do modify the database. If connection /// is nil then the utility connection is used. /// </summary> /// <param name="c"></param> /// <param name="ex"></param> /// <returns></returns> internal async Task <ExecuteResponse> execute(StoreConnection c, ExecuteRequest ex) { if (c == null) { connsMu.EnterReadLock(); try { c = conns[defaultConnID]; } finally { connsMu.ExitReadLock(); } } c.SetLastUsedNow(); var start = DateTime.Now; var cmd = new Command { Typ = CommandType.execute, Sub = new databaseSub { ConnID = c.ID, Atomic = ex.Atomic, Queries = ex.Queries, Timings = ex.Timings } }; var f = await raft.Accept(cmd).ThrowOnError(); if (f is FsmExecuteResponse <Command> ) { return(new ExecuteResponse { Results = (f as FsmExecuteResponse <Command>).Results, Time = (DateTime.Now - start).TotalSeconds, Raft = new RaftResponse { NodeID = ID } }); } else if (f is ErrorResponse <Command> ) { throw new Exception((f as ErrorResponse <Command>).Error); } else { throw new Exception("unsupported type"); } }
internal async Task <ExecuteResponse> executeOrAbort(StoreConnection c, ExecuteRequest ex) { if (c == null) { connsMu.EnterReadLock(); try { c = conns[defaultConnID]; } finally { connsMu.ExitReadLock(); } } bool errored = false; try { var f = await c.Store.execute(c, ex); errored = f.Results.Any(r => !string.IsNullOrEmpty(r.Error)); return(f); } catch (Exception e) { errored = true; c.Logger.LogError(e.ToString()); throw; } finally { if (errored) { try { await c.AbortTransaction(); } catch (Exception e) { c.Logger.LogWarning($"WARNING: failed to abort transaction on {c}: {e.Message}"); } } } }
/// <summary> /// ExecuteOrAbort executes the requests, but aborts any active transaction /// on the underlying database in the case of any error. /// </summary> /// <param name="ex"></param> /// <returns></returns> public async Task <ExecuteResponse> ExecuteOrAbort(ExecuteRequest ex) { await dbMu.WaitAsync(); try { if (db != null) { return(await Store.executeOrAbort(this, ex)); } else { throw new ConnectionDoesNotExistException(); } } finally { dbMu.Release(); } }
/// <summary> /// ExecuteOrAbort executes the requests, but aborts any active transaction /// on the underlying database in the case of any error. Any changes are made /// using the database connection built-in to the Store. /// </summary> /// <param name="ex"></param> /// <returns></returns> public async Task <ExecuteResponse> ExecuteOrAbort(ExecuteRequest ex) { return(await executeOrAbort(null, ex)); }