public async Task NotificationToAllAsync <T>(ApiNotificationResponseModel <T> message, CancellationToken cancellationToken) { await _webSocketConnectionsService.SendToAllAsync(message, cancellationToken); await _notificationQuery.AddNotification(message); }
private async Task <List <FileIndexItem> > SyncTaskInternal(Tuple <string, string, WatcherChangeTypes> watcherOutput) { var(fullFilePath, toPath, type) = watcherOutput; var operation = CreateNewRequestTelemetry(fullFilePath); var syncData = new List <FileIndexItem>(); _logger !.LogInformation($"[SyncWatcherConnector] [{fullFilePath}] - [{toPath}] - [{type}]"); if (type == WatcherChangeTypes.Renamed && !string.IsNullOrEmpty(toPath)) { // from path sync var path = _appSettings !.FullPathToDatabaseStyle(fullFilePath); await _synchronize !.Sync(path); syncData.Add(new FileIndexItem(_appSettings.FullPathToDatabaseStyle(fullFilePath)) { IsDirectory = true, Status = FileIndexItem.ExifStatus.NotFoundSourceMissing }); // and now to-path sync var pathToDatabaseStyle = _appSettings.FullPathToDatabaseStyle(toPath); syncData.AddRange(await _synchronize.Sync(pathToDatabaseStyle)); } else { syncData = await _synchronize !.Sync(_appSettings !.FullPathToDatabaseStyle(fullFilePath)); } var filtered = FilterBefore(syncData); if (!filtered.Any()) { EndRequestOperation(operation); return(syncData); } // update users who are active right now var webSocketResponse = new ApiNotificationResponseModel <List <FileIndexItem> >(filtered, ApiNotificationType.SyncWatcherConnector); await _connectionsService !.SendToAllAsync(JsonSerializer.Serialize(webSocketResponse, DefaultJsonSerializer.CamelCase), CancellationToken.None); // And update the query Cache _query !.CacheUpdateItem(filtered.Where(p => p.Status == FileIndexItem.ExifStatus.Ok || p.Status == FileIndexItem.ExifStatus.Deleted).ToList()); // remove files that are not in the index from cache _query.RemoveCacheItem(filtered.Where(p => p.Status == FileIndexItem.ExifStatus.NotFoundNotInIndex || p.Status == FileIndexItem.ExifStatus.NotFoundSourceMissing).ToList()); if (_serviceScope != null) { await _query.DisposeAsync(); } EndRequestOperation(operation); return(syncData); }
public Task <NotificationItem> AddNotification <T>(ApiNotificationResponseModel <T> content) { var stringMessage = JsonSerializer.Serialize(content, DefaultJsonSerializer.CamelCase); return(AddNotification(stringMessage)); }
private async Task TaskRun(List <FileIndexItem> fileIndexResultsList) { var webSocketResponse = new ApiNotificationResponseModel <List <FileIndexItem> >(fileIndexResultsList, ApiNotificationType.MetaUpdate); var realtimeConnectionsService = _scopeFactory.CreateScope() .ServiceProvider.GetRequiredService <IRealtimeConnectionsService>(); await realtimeConnectionsService.NotificationToAllAsync(webSocketResponse, CancellationToken.None); }
public Task SendToAllAsync <T>(ApiNotificationResponseModel <T> message, CancellationToken cancellationToken) { var stringMessage = JsonSerializer.Serialize(message, DefaultJsonSerializer.CamelCase); FakeSendToAllAsync.Add(stringMessage); return(Task.CompletedTask); }
private async Task HeartbeatAsync(CancellationToken cancellationToken) { while (!cancellationToken.IsCancellationRequested) { var webSocketResponse = new ApiNotificationResponseModel <HeartbeatModel>(new HeartbeatModel(SpeedInSeconds), ApiNotificationType.Heartbeat); await _connectionsService.SendToAllAsync(webSocketResponse, cancellationToken); await Task.Delay(TimeSpan.FromSeconds(SpeedInSeconds), cancellationToken); } }
/// <summary> /// Update other users with a message from SyncViewModel /// </summary> /// <param name="syncResultsList">SyncViewModel</param> /// <param name="type">optional debug name</param> /// <returns>Completed send of Socket SendToAllAsync</returns> private async Task SyncMessageToSocket(IEnumerable <SyncViewModel> syncResultsList, ApiNotificationType type = ApiNotificationType.Unknown) { var list = syncResultsList.Select(t => new FileIndexItem(t.FilePath) { Status = t.Status, IsDirectory = true }).ToList(); var webSocketResponse = new ApiNotificationResponseModel < List <FileIndexItem> >(list, type); await _notificationQuery.AddNotification(webSocketResponse); await _connectionsService.SendToAllAsync(webSocketResponse, CancellationToken.None); }
public async Task <IActionResult> Replace(string f, string fieldName, string search, string replace, bool collections = true) { var stopwatch = StopWatchLogger.StartUpdateReplaceStopWatch(); var fileIndexResultsList = await _metaReplaceService .Replace(f, fieldName, search, replace, collections); var resultsOkOrDeleteList = fileIndexResultsList.Where( p => p.Status == FileIndexItem.ExifStatus.Ok || p.Status == FileIndexItem.ExifStatus.Deleted).ToList(); var changedFileIndexItemName = resultsOkOrDeleteList. ToDictionary(item => item.FilePath, item => new List <string> { fieldName }); // Update > _bgTaskQueue.QueueBackgroundWorkItem(async _ => { var metaUpdateService = _scopeFactory.CreateScope() .ServiceProvider.GetRequiredService <IMetaUpdateService>(); await metaUpdateService .UpdateAsync(changedFileIndexItemName, resultsOkOrDeleteList, null, collections, false, 0); }); // before sending not founds new StopWatchLogger(_logger).StopUpdateReplaceStopWatch("update", f, collections, stopwatch); // When all items are not found if (!resultsOkOrDeleteList.Any()) { return(NotFound(fileIndexResultsList)); } // Push direct to socket when update or replace to avoid undo after a second var webSocketResponse = new ApiNotificationResponseModel <List <FileIndexItem> >(resultsOkOrDeleteList, ApiNotificationType.Replace); await _connectionsService.NotificationToAllAsync(webSocketResponse, CancellationToken.None); return(Json(fileIndexResultsList)); }
public async Task <IActionResult> Rename(string f, string to, bool collections = true, bool currentStatus = true) { var rename = await new RenameService(_query, _iStorage).Rename(f, to, collections); // When all items are not found if (rename.All(p => p.Status != FileIndexItem.ExifStatus.Ok)) { return(NotFound(rename)); } var webSocketResponse = new ApiNotificationResponseModel <List <FileIndexItem> >(rename, ApiNotificationType.Rename); await _notificationQuery.AddNotification(webSocketResponse); await _connectionsService.SendToAllAsync(webSocketResponse, CancellationToken.None); return(Json(currentStatus ? rename.Where(p => p.Status != FileIndexItem.ExifStatus.NotFoundSourceMissing).ToList() : rename)); }
internal async Task WorkItem(string subPath, IStorage subPathStorage, IStorage thumbnailStorage) { try { _logger.LogInformation($"[ThumbnailGenerationController] start {subPath}"); var thumbnail = new Thumbnail(subPathStorage, thumbnailStorage, _logger); var thumbs = await thumbnail.CreateThumb(subPath); var getAllFilesAsync = await _query.GetAllFilesAsync(subPath); var result = new List <FileIndexItem>(); foreach (var item in getAllFilesAsync.Where(item => thumbs.FirstOrDefault(p => p.Item1 == item.FilePath).Item2)) { if (item.Tags.Contains("!delete!")) { continue; } item.SetLastEdited(); result.Add(item); } if (!result.Any()) { return; } var webSocketResponse = new ApiNotificationResponseModel <List <FileIndexItem> >(result, ApiNotificationType.ThumbnailGeneration); await _connectionsService.SendToAllAsync(webSocketResponse, CancellationToken.None); _logger.LogInformation($"[ThumbnailGenerationController] done {subPath}"); } catch (UnauthorizedAccessException e) { _logger.LogError($"[ThumbnailGenerationController] catch-ed exception {e.Message}", e); } }
public async Task <IActionResult> UploadToFolder() { var to = Request.Headers["to"].ToString(); if (string.IsNullOrWhiteSpace(to)) { return(BadRequest("missing 'to' header")); } var parentDirectory = GetParentDirectoryFromRequestHeader(); if (parentDirectory == null) { return(NotFound(new ImportIndexItem { Status = ImportStatus.ParentDirectoryNotFound })); } var tempImportPaths = await Request.StreamFile(_appSettings, _selectorStorage); var fileIndexResultsList = await _import.Preflight(tempImportPaths, new ImportSettingsModel { IndexMode = false }); for (var i = 0; i < fileIndexResultsList.Count; i++) { if (fileIndexResultsList[i].Status != ImportStatus.Ok) { continue; } var tempFileStream = _iHostStorage.ReadStream(tempImportPaths[i]); var fileName = Path.GetFileName(tempImportPaths[i]); // subPath is always unix style var subPath = PathHelper.AddSlash(parentDirectory) + fileName; if (parentDirectory == "/") { subPath = parentDirectory + fileName; } // to get the output in the result right fileIndexResultsList[i].FileIndexItem.FileName = fileName; fileIndexResultsList[i].FileIndexItem.ParentDirectory = parentDirectory; fileIndexResultsList[i].FilePath = subPath; // Do sync action before writing it down fileIndexResultsList[i].FileIndexItem = await SyncItem(fileIndexResultsList[i].FileIndexItem); var writeStatus = await _iStorage.WriteStreamAsync(tempFileStream, subPath + ".tmp"); await tempFileStream.DisposeAsync(); // to avoid partly written stream to be read by an other application _iStorage.FileDelete(subPath); _iStorage.FileMove(subPath + ".tmp", subPath); _logger.LogInformation($"write {subPath} is {writeStatus}"); // clear directory cache _query.RemoveCacheParentItem(subPath); var deleteStatus = _iHostStorage.FileDelete(tempImportPaths[i]); _logger.LogInformation($"[UploadController] delete {tempImportPaths[i]} is {deleteStatus}"); var parentPath = Directory.GetParent(tempImportPaths[i])?.FullName; if (!string.IsNullOrEmpty(parentPath) && parentPath != _appSettings.TempFolder) { _iHostStorage.FolderDelete(parentPath); } await _metaExifThumbnailService.AddMetaThumbnail(subPath, fileIndexResultsList[i].FileIndexItem.FileHash); } // send all uploads as list var socketResult = fileIndexResultsList .Where(p => p.Status == ImportStatus.Ok) .Select(item => item.FileIndexItem).ToList(); var webSocketResponse = new ApiNotificationResponseModel <List <FileIndexItem> >( socketResult, ApiNotificationType.UploadFile); await _connectionsService.NotificationToAllAsync(webSocketResponse, CancellationToken.None); // Wrong input (extension is not allowed) if (fileIndexResultsList.All(p => p.Status == ImportStatus.FileError)) { _logger.LogInformation($"Wrong input extension is not allowed" + $" {string.Join(",",fileIndexResultsList.Select(p => p.FilePath))}"); Response.StatusCode = 415; } return(Json(fileIndexResultsList)); }
internal async Task PushToSockets(List <FileIndexItem> updatedList) { var webSocketResponse = new ApiNotificationResponseModel <List <FileIndexItem> >(updatedList, ApiNotificationType.ManualBackgroundSync); await _connectionsService.SendToAllAsync(webSocketResponse, CancellationToken.None); }
public async Task Invoke(HttpContext context) { if (ValidateOrigin(context)) { if (context.WebSockets.IsWebSocketRequest) { WebSocket webSocket = await context.WebSockets.AcceptWebSocketAsync(); if (!context.User.Identity.IsAuthenticated) { // Status Code 1008 PolicyViolation await webSocket.CloseOutputAsync(WebSocketCloseStatus.PolicyViolation, "Please login first", CancellationToken.None); return; } WebSocketConnection webSocketConnection = new WebSocketConnection(webSocket, _options.ReceivePayloadBufferSize); async void OnWebSocketConnectionOnNewConnection(object sender, EventArgs message) { await Task.Delay(150); try { var welcomeMessage = new ApiNotificationResponseModel <HeartbeatModel>(new HeartbeatModel(null)) { Type = ApiNotificationType.Welcome, }; await webSocketConnection.SendAsync(JsonSerializer.Serialize(welcomeMessage, DefaultJsonSerializer.CamelCase), CancellationToken.None); } catch (WebSocketException) { // if the client is closing the socket the wrong way } } webSocketConnection.NewConnection += OnWebSocketConnectionOnNewConnection; _connectionsService.AddConnection(webSocketConnection); await webSocketConnection.ReceiveMessagesUntilCloseAsync(); if (webSocketConnection.CloseStatus.HasValue) { await webSocket.CloseOutputAsync(webSocketConnection.CloseStatus.Value, webSocketConnection.CloseStatusDescription, CancellationToken.None); } _connectionsService.RemoveConnection(webSocketConnection.Id); } else { context.Response.StatusCode = StatusCodes.Status400BadRequest; } } else { context.Response.StatusCode = StatusCodes.Status403Forbidden; } }
public Task NotificationToAllAsync <T>(ApiNotificationResponseModel <T> message, CancellationToken cancellationToken) { FakeSendToAllAsync.Add(new Tuple <string, DateTime>(JsonSerializer.Serialize(message), DateTime.UtcNow)); return(Task.CompletedTask); }