internal static bool TryReadRoutineData(string directory, string routineId, out RoutineDataEnvelope dataEnvelope, out string eTag) { var fileName = routineId + ".json"; var filePath = Path.Combine(directory, fileName); if (File.Exists(filePath)) { for (var i = 0; i < 10; i++) { try { var json = File.ReadAllText(filePath); eTag = new DateTimeOffset(File.GetLastWriteTimeUtc(filePath)).ToString("o"); dataEnvelope = JsonConvert.DeserializeObject <RoutineDataEnvelope>( json, CloudEventsSerialization.JsonSerializerSettings); return(true); } catch (IOException) // File is being used by another process. { Thread.Sleep(1); continue; } } } eTag = null; dataEnvelope = null; return(false); }
private void UpsertRoutineData(string routineId, string expectedETag, Action <RoutineDataEnvelope> updateAction) { var fileName = routineId + ".json"; var filePath = Path.Combine(_fabric.RoutinesDirectory, fileName); var fileStream = new FileStream(filePath, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.Read, 4096); #warning need more precise error handling here - what if file is locked? using (fileStream) { RoutineDataEnvelope routineDataEnvelope; if (fileStream.Length > 0) { var routineETag = new DateTimeOffset(File.GetLastWriteTimeUtc(filePath)).ToString("o"); if (!string.IsNullOrEmpty(expectedETag) && expectedETag != routineETag) { throw new ConcurrentRoutineExecutionException( new ETagMismatchException()); } using (var textReader = new StreamReader(fileStream, Encoding.UTF8, true, 512, leaveOpen: true)) routineDataEnvelope = (RoutineDataEnvelope)_jsonSerializer.Deserialize(textReader, typeof(RoutineDataEnvelope)); fileStream.Position = 0; } else { routineDataEnvelope = new RoutineDataEnvelope(); } updateAction(routineDataEnvelope); using (var textWriter = new StreamWriter(fileStream, Encoding.UTF8, 512, leaveOpen: true)) _jsonSerializer.Serialize(textWriter, routineDataEnvelope); fileStream.SetLength(fileStream.Position); } }