Fix SignalR client in web to use connection pooling

This commit is contained in:
Fergal Moran
2018-05-12 05:47:43 +01:00
parent 8b647ec7ef
commit a7dbab71cf
5 changed files with 52 additions and 19 deletions

View File

@@ -59,7 +59,7 @@ export class AppComponent implements OnInit {
this._signalrService this._signalrService
.init('userupdates') .init('userupdates')
.then((listener) => { .then((listener) => {
listener.on<string>(chatterChannel) listener.on<string>('userupdates', chatterChannel)
.subscribe(result => { .subscribe(result => {
this._toastyService.info(result); this._toastyService.info(result);
}); });

View File

@@ -48,13 +48,13 @@ export class EntryListItemComponent implements OnInit {
this.entry.uid this.entry.uid
}__info_processed`; }__info_processed`;
listener listener
.on<AudioProcessingMessageModel>(updateChannel) .on<AudioProcessingMessageModel>('audioprocessing', updateChannel)
.subscribe((result) => { .subscribe((result) => {
this.percentageProcessed = result.percentage; this.percentageProcessed = result.percentage;
this.currentSpeed = result.currentSpeed; this.currentSpeed = result.currentSpeed;
}); });
listener listener
.on<PodcastEntryModel>(processedChannel) .on<PodcastEntryModel>('audioprocessing', processedChannel)
.subscribe((result) => { .subscribe((result) => {
this.entry = result; this.entry = result;
if (this.entry.processingStatus === 'Processed') { if (this.entry.processingStatus === 'Processed') {

View File

@@ -26,7 +26,7 @@ export class ChatService extends BaseService {
if (r) { if (r) {
this._signalRService.init('chat').then((listener) => { this._signalRService.init('chat').then((listener) => {
listener listener
.on<ChatModel>('SendMessage') .on<ChatModel>('chat', 'SendMessage')
.subscribe((message: ChatModel) => { .subscribe((message: ChatModel) => {
console.log( console.log(
'chat-widget.component', 'chat-widget.component',

View File

@@ -4,34 +4,62 @@ import { HubConnection, HubConnectionBuilder, LogLevel } from '@aspnet/signalr';
import { environment } from 'environments/environment'; import { environment } from 'environments/environment';
import { Observable, Subscriber } from 'rxjs'; import { Observable, Subscriber } from 'rxjs';
class HubListener {
constructor(connection: HubConnection) {
this.connection = connection;
this.isConnecting = false;
this.isConnected = false;
}
connection: HubConnection;
isConnected: boolean;
isConnecting: boolean;
}
interface HubCollection {
[hubName: string]: HubListener;
}
@Injectable() @Injectable()
export class SignalRService { export class SignalRService {
private _connected: boolean = false; private connectionPool: HubCollection = {};
private _connection: HubConnection;
constructor(private _auth: PodnomsAuthService) {} constructor(private _auth: PodnomsAuthService) {}
public init(hub: string): Promise<SignalRService> { public init(hubName: string): Promise<SignalRService> {
return new Promise((resolve) => { return new Promise((resolve) => {
const url = `${environment.SIGNALR_HOST}/hubs/${hub}`; const url = `${environment.SIGNALR_HOST}/hubs/${hubName}`;
const token = this._auth.getToken(); const token = this._auth.getToken();
this._connection = new HubConnectionBuilder() let hub = this.connectionPool[hubName];
if (!hub) {
const connection = new HubConnectionBuilder()
.configureLogging(LogLevel.Debug) .configureLogging(LogLevel.Debug)
.withUrl(url + '?token=' + token) .withUrl(url + '?token=' + token)
.build(); .build();
this.connectionPool[hubName] = new HubListener(connection);
}
resolve(this); resolve(this);
}); });
} }
public on<T>(channel: string): Observable<T> { public on<T>(hub: string, channel: string): Observable<T> {
const listener = new Observable<T>((subscriber: Subscriber<T>) => { const listener = new Observable<T>((subscriber: Subscriber<T>) => {
this._connection.on(channel, (message) => { const h = this.connectionPool[hub];
h.connection.on(channel, (message) => {
const result: T = message as T; const result: T = message as T;
subscriber.next(result); subscriber.next(result);
}); });
h.connection.onclose(() => {
h.isConnected = false;
});
if (!h.isConnected && !h.isConnecting) {
h.isConnecting = true;
h.connection.start().then(() => {
h.isConnected = true;
h.isConnecting = false;
this.connectionPool[hub] = h;
}); });
if (!this._connected) {
this._connection.start().then(() => (this._connected = true));
} }
this.connectionPool[hub] = h;
});
return listener; return listener;
} }
} }

View File

@@ -4,6 +4,7 @@ using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using PodNoms.Api.Models; using PodNoms.Api.Models;
using PodNoms.Api.Utils;
namespace PodNoms.Api.Persistence { namespace PodNoms.Api.Persistence {
public interface IPodcastRepository : IRepository<Podcast> { public interface IPodcastRepository : IRepository<Podcast> {
@@ -21,7 +22,6 @@ namespace PodNoms.Api.Persistence {
.FirstOrDefaultAsync(); .FirstOrDefaultAsync();
return ret; return ret;
} }
public async Task<IEnumerable<Podcast>> GetAllForUserAsync(string userId) { public async Task<IEnumerable<Podcast>> GetAllForUserAsync(string userId) {
var ret = GetAll() var ret = GetAll()
.Where(u => u.AppUser.Id == userId) .Where(u => u.AppUser.Id == userId)
@@ -29,6 +29,11 @@ namespace PodNoms.Api.Persistence {
.OrderByDescending(p => p.Id); .OrderByDescending(p => p.Id);
return await ret.ToListAsync(); return await ret.ToListAsync();
} }
public new Podcast AddOrUpdate(Podcast podcast) {
if (string.IsNullOrEmpty(podcast.TemporaryImageUrl)) {
podcast.TemporaryImageUrl = $"standard/podcast-image-{Randomisers.RandomInteger(1, 16)}.png";
}
return base.AddOrUpdate(podcast);
}
} }
} }