public override async Task stream(StreamRequest request, IServerStreamWriter <VideoChunk> responseStream, ServerCallContext context) { var findResult = await _repo.FindById(request.VideoId); if (findResult == null) { throw new RpcException(new Status(StatusCode.NotFound, "Video not found")); } var downloadRequest = new DownloadRequest { Id = findResult.ExternalFileId, Options = new FileOptions { Start = 0 } }; var remoteStream = _fileServerClient.download(downloadRequest); var fileStream = remoteStream.ResponseStream; while (await fileStream.MoveNext(context.CancellationToken)) { var chunk = fileStream.Current.Chunk; // TODO: Transcode Chunk await responseStream.WriteAsync(new VideoChunk { VideoId = request.VideoId, Chunk = chunk }); } }
public override async Task stream(StreamRequest request, IServerStreamWriter <VideoChunk> responseStream, ServerCallContext context) { var findResult = await _repo.FindById(request.VideoId); if (findResult == null) { throw new RpcException(new Status(StatusCode.NotFound, "Video not found")); } if (!string.IsNullOrWhiteSpace(findResult.ExternalFileId)) { var downloadRequest = new DownloadRequest { Id = findResult.ExternalFileId, Options = new FileOptions { Start = 0 } }; var remoteStream = _fileServerClient.download(downloadRequest); var fileStream = remoteStream.ResponseStream; while (await fileStream.MoveNext(context.CancellationToken)) { var chunk = fileStream.Current.Chunk; // TODO: Transcode Chunk await responseStream.WriteAsync(new VideoChunk { VideoId = request.VideoId, Chunk = chunk }); } } else if (!string.IsNullOrWhiteSpace(findResult.StreamName)) { var subscriber = _redisMultiplexer.GetSubscriber(); var observable = Observable.Create <VideoChunk>(async(obs, ct) => { var channel = findResult.StreamName; await subscriber.SubscribeAsync(channel, (_, message) => { obs.OnNext(FromRedisValue(message)); }).ConfigureAwait(false); return(Disposable.Create(() => subscriber.Unsubscribe(channel))); }); var breakCount = 0; using (var subscription = observable.Subscribe(async(message) => { try { if (breakCount < 3) { await responseStream.WriteAsync(message); breakCount = 0; } } catch (Exception e) { breakCount++; _logger.LogError(e, "Error while writing video chunk to response."); } })) { _logger.LogInformation("User {UserId} subscribed to video {VideoId}", request.UserId, request.VideoId); //This is to prevent the response stream from being disposed while (breakCount < 3) { await Task.Delay(1000); } } } }