private static IRouteResponse SaveLogEntry(AuditLog entry) { using (var conn = OpenConnection()) { CreateLogEntry(conn, entry); } return(RouteResponse.OK()); }
private static IRouteResponse BeginTransaction(RequestCommon req) { var conn = OpenConnection(); var transaction = conn.BeginTransaction(); transactions[req.UserId] = new Transaction(transaction, conn); return(RouteResponse.OK()); }
private static IRouteResponse ImportEntity(EntityData entity) { IRouteResponse resp = RouteResponse.OK(); // Evil! // Lock the whole process in case another async call fails and the client calls abort which gets // processed and then more import calls are received. lock (schemaLocker) { // We assume there's data! using (var tconn = OpenConnection()) { CheckForTable(tconn, entity.StoreName); // Somewhat annoyingly we actually have to check all the records for any new field. entity.StoreData.ForEach(d => { foreach (var prop in d.Properties()) { CheckForField(tconn, entity.StoreName, prop.Name); } }); } } var tinfo = transactions[entity.UserId]; var transaction = tinfo.t; var conn = tinfo.c; try { Interlocked.Increment(ref tinfo.transactionCount); Console.WriteLine($"{tinfo.transactionCount} {tinfo.rollbackCount} {tinfo.c.State}"); for (int n = 0; n < entity.StoreData.Count && Interlocked.Read(ref tinfo.rollbackCount) == 0; ++n) { lock (schemaLocker) { InsertRecord(conn, transaction, entity.UserId, entity.StoreName, entity.StoreData[n]); } } } catch (Exception ex) { Console.WriteLine(ex.Message); resp = RouteResponse.ServerError(new { Error = ex.Message }); } finally { Interlocked.Decrement(ref tinfo.transactionCount); } return(resp); }
private static IRouteResponse Load(LoadStore store) { Console.WriteLine($"Load store {store.StoreName} for user {store.UserId}"); using (var conn = OpenConnection()) { CheckForTable(conn, store.StoreName); var data = LoadStore(conn, store.StoreName, store.UserId); return(RouteResponse.OK(data)); } }
private static IRouteResponse CommitTransaction(RequestCommon req) { Console.WriteLine("Committing transactions..."); var tinfo = transactions[req.UserId]; Console.WriteLine($"{tinfo.transactionCount} {tinfo.rollbackCount} {tinfo.c.State}"); tinfo.t.Commit(); tinfo.c.Close(); transactions.Remove(req.UserId, out _); return(RouteResponse.OK()); }
private static IRouteResponse ImportAuditLog(AuditLogEntries log) { using (var conn = OpenConnection()) { // Evil! lock (schemaLocker) { UpdateSchema(conn, log.Entries); // The CRUD operations have to be in the lock operation so that another request doesn't update the schema while we're updating the record. log.Entries.ForEach(l => PersistTransaction(conn, l, log.UserId)); } } return(RouteResponse.OK()); }
private static IRouteResponse Save(SaveStore store) { var logs = JsonConvert.DeserializeObject <List <AuditLog> >(store.AuditLog); using (var conn = OpenConnection()) { // Evil! lock (schemaLocker) { UpdateSchema(conn, logs); // The CRUD operations have to be in the lock operation so that another request doesn't update the schema while we're updating the record. logs.ForEach(l => PersistTransaction(conn, l, store.UserId)); } } return(RouteResponse.OK()); }
private static IRouteResponse RollbackTransaction(RequestCommon req) { var tinfo = transactions[req.UserId]; Interlocked.Increment(ref tinfo.rollbackCount); while (Interlocked.Read(ref tinfo.transactionCount) > 0) { // Thread.Sleep(0) is evil, see some article I wrote somewhere regarding that. Thread.Sleep(1); } Console.WriteLine($"Abort {req.UserId}"); transactions[req.UserId].t.Rollback(); transactions[req.UserId].c.Close(); transactions.Remove(req.UserId, out _); // No need to decrement the rollback counter as we're all done. return(RouteResponse.OK()); }