@ -15,30 +15,20 @@ namespace MediaBrowser.Server.Implementations.Notifications
{
{
public class SqliteNotificationsRepository : BaseSqliteRepository , INotificationsRepository
public class SqliteNotificationsRepository : BaseSqliteRepository , INotificationsRepository
{
{
private IDbConnection _connection ;
public SqliteNotificationsRepository ( ILogManager logManager , IServerApplicationPaths appPaths , IDbConnector dbConnector ) : base ( logManager , dbConnector )
private readonly IServerApplicationPaths _appPaths ;
{
DbFilePath = Path . Combine ( appPaths . DataPath , "notifications.db" ) ;
}
public event EventHandler < NotificationUpdateEventArgs > NotificationAdded ;
public event EventHandler < NotificationUpdateEventArgs > NotificationAdded ;
public event EventHandler < NotificationReadEventArgs > NotificationsMarkedRead ;
public event EventHandler < NotificationReadEventArgs > NotificationsMarkedRead ;
public event EventHandler < NotificationUpdateEventArgs > NotificationUpdated ;
public event EventHandler < NotificationUpdateEventArgs > NotificationUpdated ;
private IDbCommand _replaceNotificationCommand ;
public async Task Initialize ( )
private IDbCommand _markReadCommand ;
private IDbCommand _markAllReadCommand ;
public SqliteNotificationsRepository ( ILogManager logManager , IServerApplicationPaths appPaths )
: base ( logManager )
{
{
_appPaths = appPaths ;
using ( var connection = await CreateConnection ( ) . ConfigureAwait ( false ) )
}
{
string [ ] queries = {
public async Task Initialize ( IDbConnector dbConnector )
{
var dbFile = Path . Combine ( _appPaths . DataPath , "notifications.db" ) ;
_connection = await dbConnector . Connect ( dbFile ) . ConfigureAwait ( false ) ;
string [ ] queries = {
"create table if not exists Notifications (Id GUID NOT NULL, UserId GUID NOT NULL, Date DATETIME NOT NULL, Name TEXT NOT NULL, Description TEXT, Url TEXT, Level TEXT NOT NULL, IsRead BOOLEAN NOT NULL, Category TEXT NOT NULL, RelatedId TEXT, PRIMARY KEY (Id, UserId))" ,
"create table if not exists Notifications (Id GUID NOT NULL, UserId GUID NOT NULL, Date DATETIME NOT NULL, Name TEXT NOT NULL, Description TEXT, Url TEXT, Level TEXT NOT NULL, IsRead BOOLEAN NOT NULL, Category TEXT NOT NULL, RelatedId TEXT, PRIMARY KEY (Id, UserId))" ,
"create index if not exists idx_Notifications1 on Notifications(Id)" ,
"create index if not exists idx_Notifications1 on Notifications(Id)" ,
@ -50,39 +40,8 @@ namespace MediaBrowser.Server.Implementations.Notifications
"pragma shrink_memory"
"pragma shrink_memory"
} ;
} ;
_connection . RunQueries ( queries , Logger ) ;
connection . RunQueries ( queries , Logger ) ;
}
PrepareStatements ( ) ;
}
private void PrepareStatements ( )
{
_replaceNotificationCommand = _connection . CreateCommand ( ) ;
_replaceNotificationCommand . CommandText = "replace into Notifications (Id, UserId, Date, Name, Description, Url, Level, IsRead, Category, RelatedId) values (@Id, @UserId, @Date, @Name, @Description, @Url, @Level, @IsRead, @Category, @RelatedId)" ;
_replaceNotificationCommand . Parameters . Add ( _replaceNotificationCommand , "@Id" ) ;
_replaceNotificationCommand . Parameters . Add ( _replaceNotificationCommand , "@UserId" ) ;
_replaceNotificationCommand . Parameters . Add ( _replaceNotificationCommand , "@Date" ) ;
_replaceNotificationCommand . Parameters . Add ( _replaceNotificationCommand , "@Name" ) ;
_replaceNotificationCommand . Parameters . Add ( _replaceNotificationCommand , "@Description" ) ;
_replaceNotificationCommand . Parameters . Add ( _replaceNotificationCommand , "@Url" ) ;
_replaceNotificationCommand . Parameters . Add ( _replaceNotificationCommand , "@Level" ) ;
_replaceNotificationCommand . Parameters . Add ( _replaceNotificationCommand , "@IsRead" ) ;
_replaceNotificationCommand . Parameters . Add ( _replaceNotificationCommand , "@Category" ) ;
_replaceNotificationCommand . Parameters . Add ( _replaceNotificationCommand , "@RelatedId" ) ;
_markReadCommand = _connection . CreateCommand ( ) ;
_markReadCommand . CommandText = "update Notifications set IsRead=@IsRead where Id=@Id and UserId=@UserId" ;
_markReadCommand . Parameters . Add ( _replaceNotificationCommand , "@UserId" ) ;
_markReadCommand . Parameters . Add ( _replaceNotificationCommand , "@IsRead" ) ;
_markReadCommand . Parameters . Add ( _replaceNotificationCommand , "@Id" ) ;
_markAllReadCommand = _connection . CreateCommand ( ) ;
_markAllReadCommand . CommandText = "update Notifications set IsRead=@IsRead where UserId=@UserId" ;
_markAllReadCommand . Parameters . Add ( _replaceNotificationCommand , "@UserId" ) ;
_markAllReadCommand . Parameters . Add ( _replaceNotificationCommand , "@IsRead" ) ;
}
}
/// <summary>
/// <summary>
@ -94,49 +53,52 @@ namespace MediaBrowser.Server.Implementations.Notifications
{
{
var result = new NotificationResult ( ) ;
var result = new NotificationResult ( ) ;
using ( var c md = _connection . CreateCommand ( ) )
using ( var c onnection = CreateConnection ( true ) . Result )
{
{
var clauses = new List < string > ( ) ;
using ( var cmd = connection . CreateCommand ( ) )
if ( query . IsRead . HasValue )
{
{
clauses . Add ( "IsRead=@IsRead" ) ;
var clauses = new List < string > ( ) ;
cmd . Parameters . Add ( cmd , "@IsRead" , DbType . Boolean ) . Value = query . IsRead . Value ;
}
clauses . Add ( "UserId=@UserId" ) ;
if ( query . IsRead . HasValue )
cmd . Parameters . Add ( cmd , "@UserId" , DbType . Guid ) . Value = new Guid ( query . UserId ) ;
{
clauses . Add ( "IsRead=@IsRead" ) ;
cmd . Parameters . Add ( cmd , "@IsRead" , DbType . Boolean ) . Value = query . IsRead . Value ;
}
var whereClause = " where " + string . Join ( " And " , clauses . ToArray ( ) ) ;
clauses . Add ( "UserId=@UserId" ) ;
cmd . Parameters . Add ( cmd , "@UserId" , DbType . Guid ) . Value = new Guid ( query . UserId ) ;
cmd . CommandText = string . Format ( "select count(Id) from Notifications{0};select Id,UserId,Date,Name,Description,Url,Level,IsRead,Category,RelatedId from Notifications{0} order by IsRead asc, Date desc" , whereClause ) ;
var whereClause = " where " + string . Join ( " And " , clauses . ToArray ( ) ) ;
using ( var reader = cmd . ExecuteReader ( CommandBehavior . SequentialAccess ) )
cmd . CommandText = string . Format ( "select count(Id) from Notifications{0};select Id,UserId,Date,Name,Description,Url,Level,IsRead,Category,RelatedId from Notifications{0} order by IsRead asc, Date desc" , whereClause ) ;
{
if ( reader . Read ( ) )
{
result . TotalRecordCount = reader . GetInt32 ( 0 ) ;
}
if ( reader . NextResult ( ) )
using ( var reader = cmd . ExecuteReader ( CommandBehavior . SequentialAccess ) )
{
{
var notifications = GetNotifications ( reader ) ;
if ( reader . Read ( ) )
if ( query . StartIndex . HasValue )
{
{
notifications = notifications . Skip ( query . StartIndex . Value ) ;
result . TotalRecordCount = reader . GetInt32 ( 0 ) ;
}
}
if ( query. Limit . HasValue )
if ( reader. NextResult ( ) )
{
{
notifications = notifications . Take ( query . Limit . Value ) ;
var notifications = GetNotifications ( reader ) ;
}
result . Notifications = notifications . ToArray ( ) ;
if ( query . StartIndex . HasValue )
{
notifications = notifications . Skip ( query . StartIndex . Value ) ;
}
if ( query . Limit . HasValue )
{
notifications = notifications . Take ( query . Limit . Value ) ;
}
result . Notifications = notifications . ToArray ( ) ;
}
}
}
}
return result ;
return result ;
}
}
}
}
}
@ -144,31 +106,34 @@ namespace MediaBrowser.Server.Implementations.Notifications
{
{
var result = new NotificationsSummary ( ) ;
var result = new NotificationsSummary ( ) ;
using ( var c md = _connection . CreateCommand ( ) )
using ( var c onnection = CreateConnection ( true ) . Result )
{
{
cmd . CommandText = "select Level from Notifications where UserId=@UserId and IsRead=@IsRead" ;
using ( var cmd = connection . CreateCommand ( ) )
cmd . Parameters . Add ( cmd , "@UserId" , DbType . Guid ) . Value = new Guid ( userId ) ;
cmd . Parameters . Add ( cmd , "@IsRead" , DbType . Boolean ) . Value = false ;
using ( var reader = cmd . ExecuteReader ( CommandBehavior . SequentialAccess ) )
{
{
var levels = new List < NotificationLevel > ( ) ;
cmd . CommandText = "select Level from Notifications where UserId=@UserId and IsRead=@IsRead" ;
while ( reader . Read ( ) )
cmd . Parameters . Add ( cmd , "@UserId" , DbType . Guid ) . Value = new Guid ( userId ) ;
cmd . Parameters . Add ( cmd , "@IsRead" , DbType . Boolean ) . Value = false ;
using ( var reader = cmd . ExecuteReader ( CommandBehavior . SequentialAccess ) )
{
{
levels . Add ( GetLevel ( reader , 0 ) ) ;
var levels = new List < NotificationLevel > ( ) ;
}
result . UnreadCount = levels . Count ;
while ( reader . Read ( ) )
{
levels . Add ( GetLevel ( reader , 0 ) ) ;
}
if ( levels . Count > 0 )
result . UnreadCount = levels . Count ;
{
result . MaxUnreadNotificationLevel = levels . Max ( ) ;
if ( levels . Count > 0 )
{
result . MaxUnreadNotificationLevel = levels . Max ( ) ;
}
}
}
}
return result ;
return result ;
}
}
}
}
}
@ -179,10 +144,14 @@ namespace MediaBrowser.Server.Implementations.Notifications
/// <returns>IEnumerable{Notification}.</returns>
/// <returns>IEnumerable{Notification}.</returns>
private IEnumerable < Notification > GetNotifications ( IDataReader reader )
private IEnumerable < Notification > GetNotifications ( IDataReader reader )
{
{
var list = new List < Notification > ( ) ;
while ( reader . Read ( ) )
while ( reader . Read ( ) )
{
{
yield return GetNotification ( reader ) ;
list . Add ( GetNotification ( reader ) ) ;
}
}
return list ;
}
}
private Notification GetNotification ( IDataReader reader )
private Notification GetNotification ( IDataReader reader )
@ -273,59 +242,74 @@ namespace MediaBrowser.Server.Implementations.Notifications
cancellationToken . ThrowIfCancellationRequested ( ) ;
cancellationToken . ThrowIfCancellationRequested ( ) ;
await WriteLock . WaitAsync ( cancellationToken ) . ConfigureAwait ( false ) ;
using ( var connection = await CreateConnection ( ) . ConfigureAwait ( false ) )
IDbTransaction transaction = null ;
try
{
{
transaction = _connection . BeginTransaction ( ) ;
using ( var replaceNotificationCommand = connection . CreateCommand ( ) )
{
replaceNotificationCommand . CommandText = "replace into Notifications (Id, UserId, Date, Name, Description, Url, Level, IsRead, Category, RelatedId) values (@Id, @UserId, @Date, @Name, @Description, @Url, @Level, @IsRead, @Category, @RelatedId)" ;
replaceNotificationCommand . Parameters . Add ( replaceNotificationCommand , "@Id" ) ;
replaceNotificationCommand . Parameters . Add ( replaceNotificationCommand , "@UserId" ) ;
replaceNotificationCommand . Parameters . Add ( replaceNotificationCommand , "@Date" ) ;
replaceNotificationCommand . Parameters . Add ( replaceNotificationCommand , "@Name" ) ;
replaceNotificationCommand . Parameters . Add ( replaceNotificationCommand , "@Description" ) ;
replaceNotificationCommand . Parameters . Add ( replaceNotificationCommand , "@Url" ) ;
replaceNotificationCommand . Parameters . Add ( replaceNotificationCommand , "@Level" ) ;
replaceNotificationCommand . Parameters . Add ( replaceNotificationCommand , "@IsRead" ) ;
replaceNotificationCommand . Parameters . Add ( replaceNotificationCommand , "@Category" ) ;
replaceNotificationCommand . Parameters . Add ( replaceNotificationCommand , "@RelatedId" ) ;
IDbTransaction transaction = null ;
try
{
transaction = connection . BeginTransaction ( ) ;
_replaceNotificationCommand . GetParameter ( 0 ) . Value = new Guid ( notification . Id ) ;
replaceNotificationCommand. GetParameter ( 0 ) . Value = new Guid ( notification . Id ) ;
_replaceNotificationCommand . GetParameter ( 1 ) . Value = new Guid ( notification . UserId ) ;
replaceNotificationCommand. GetParameter ( 1 ) . Value = new Guid ( notification . UserId ) ;
_replaceNotificationCommand . GetParameter ( 2 ) . Value = notification . Date . ToUniversalTime ( ) ;
replaceNotificationCommand. GetParameter ( 2 ) . Value = notification . Date . ToUniversalTime ( ) ;
_replaceNotificationCommand . GetParameter ( 3 ) . Value = notification . Name ;
replaceNotificationCommand. GetParameter ( 3 ) . Value = notification . Name ;
_replaceNotificationCommand . GetParameter ( 4 ) . Value = notification . Description ;
replaceNotificationCommand. GetParameter ( 4 ) . Value = notification . Description ;
_replaceNotificationCommand . GetParameter ( 5 ) . Value = notification . Url ;
replaceNotificationCommand. GetParameter ( 5 ) . Value = notification . Url ;
_replaceNotificationCommand . GetParameter ( 6 ) . Value = notification . Level . ToString ( ) ;
replaceNotificationCommand. GetParameter ( 6 ) . Value = notification . Level . ToString ( ) ;
_replaceNotificationCommand . GetParameter ( 7 ) . Value = notification . IsRead ;
replaceNotificationCommand. GetParameter ( 7 ) . Value = notification . IsRead ;
_replaceNotificationCommand . GetParameter ( 8 ) . Value = string . Empty ;
replaceNotificationCommand. GetParameter ( 8 ) . Value = string . Empty ;
_replaceNotificationCommand . GetParameter ( 9 ) . Value = string . Empty ;
replaceNotificationCommand. GetParameter ( 9 ) . Value = string . Empty ;
_replaceNotificationCommand . Transaction = transaction ;
replaceNotificationCommand. Transaction = transaction ;
_replaceNotificationCommand . ExecuteNonQuery ( ) ;
replaceNotificationCommand. ExecuteNonQuery ( ) ;
transaction . Commit ( ) ;
transaction . Commit ( ) ;
}
}
catch ( OperationCanceledException )
catch ( OperationCanceledException )
{
{
if ( transaction ! = null )
if ( transaction ! = null )
{
{
transaction . Rollback ( ) ;
transaction . Rollback ( ) ;
}
}
throw ;
throw ;
}
}
catch ( Exception e )
catch ( Exception e )
{
{
Logger . ErrorException ( "Failed to save notification:" , e ) ;
Logger . ErrorException ( "Failed to save notification:" , e ) ;
if ( transaction ! = null )
if ( transaction ! = null )
{
{
transaction . Rollback ( ) ;
transaction . Rollback ( ) ;
}
}
throw ;
throw ;
}
}
finally
finally
{
{
if ( transaction ! = null )
if ( transaction ! = null )
{
{
transaction . Dispose ( ) ;
transaction . Dispose ( ) ;
}
}
}
}
WriteLock . Release ( ) ;
}
}
}
}
@ -366,51 +350,58 @@ namespace MediaBrowser.Server.Implementations.Notifications
{
{
cancellationToken . ThrowIfCancellationRequested ( ) ;
cancellationToken . ThrowIfCancellationRequested ( ) ;
await WriteLock . WaitAsync ( cancellationToken ) . ConfigureAwait ( false ) ;
using ( var connection = await CreateConnection ( ) . ConfigureAwait ( false ) )
{
using ( var markAllReadCommand = connection . CreateCommand ( ) )
{
markAllReadCommand . CommandText = "update Notifications set IsRead=@IsRead where UserId=@UserId" ;
IDbTransaction transaction = null ;
markAllReadCommand . Parameters . Add ( markAllReadCommand , "@UserId" ) ;
markAllReadCommand . Parameters . Add ( markAllReadCommand , "@IsRead" ) ;
try
IDbTransaction transaction = null ;
{
cancellationToken . ThrowIfCancellationRequested ( ) ;
transaction = _connection . BeginTransaction ( ) ;
try
{
cancellationToken . ThrowIfCancellationRequested ( ) ;
_markAllReadCommand . GetParameter ( 0 ) . Value = new Guid ( userId ) ;
transaction = connection . BeginTransaction ( ) ;
_markAllReadCommand . GetParameter ( 1 ) . Value = isRead ;
_markAllReadCommand . ExecuteNonQuery ( ) ;
markAllReadCommand . GetParameter ( 0 ) . Value = new Guid ( userId ) ;
markAllReadCommand . GetParameter ( 1 ) . Value = isRead ;
transaction . Commit ( ) ;
markAllReadCommand . ExecuteNonQuery ( ) ;
}
catch ( OperationCanceledException )
{
if ( transaction ! = null )
{
transaction . Rollback ( ) ;
}
throw ;
transaction . Commit ( ) ;
}
}
catch ( Exception e )
catch ( OperationCanceledException )
{
{
Logger . ErrorException ( "Failed to save notification:" , e ) ;
if ( transaction ! = null )
{
transaction . Rollback ( ) ;
}
if ( transaction ! = null )
throw ;
{
}
transaction . Rollback ( ) ;
catch ( Exception e )
}
{
Logger . ErrorException ( "Failed to save notification:" , e ) ;
throw ;
if ( transaction ! = null )
}
{
finally
transaction . Rollback ( ) ;
{
}
if ( transaction ! = null )
{
transaction . Dispose ( ) ;
}
WriteLock . Release ( ) ;
throw ;
}
finally
{
if ( transaction ! = null )
{
transaction . Dispose ( ) ;
}
}
}
}
}
}
}
@ -418,72 +409,66 @@ namespace MediaBrowser.Server.Implementations.Notifications
{
{
cancellationToken . ThrowIfCancellationRequested ( ) ;
cancellationToken . ThrowIfCancellationRequested ( ) ;
await WriteLock . WaitAsync ( cancellationToken ) . ConfigureAwait ( false ) ;
using ( var connection = await CreateConnection ( ) . ConfigureAwait ( false ) )
IDbTransaction transaction = null ;
try
{
{
cancellationToken . ThrowIfCancellationRequested ( ) ;
using ( var markReadCommand = connection . CreateCommand ( ) )
{
markReadCommand . CommandText = "update Notifications set IsRead=@IsRead where Id=@Id and UserId=@UserId" ;
transaction = _connection . BeginTransaction ( ) ;
markReadCommand . Parameters . Add ( markReadCommand , "@UserId" ) ;
markReadCommand . Parameters . Add ( markReadCommand , "@IsRead" ) ;
markReadCommand . Parameters . Add ( markReadCommand , "@Id" ) ;
_markReadCommand . GetParameter ( 0 ) . Value = new Guid ( userId ) ;
IDbTransaction transaction = null ;
_markReadCommand . GetParameter ( 1 ) . Value = isRead ;
foreach ( var id in notificationIdList )
try
{
{
_markReadCommand . GetParameter ( 2 ) . Value = id ;
cancellationToken . ThrowIfCancellationRequested ( ) ;
_markReadCommand . Transaction = transaction ;
transaction = connection . BeginTransaction ( ) ;
_markReadCommand . ExecuteNonQuery ( ) ;
markReadCommand . GetParameter ( 0 ) . Value = new Guid ( userId ) ;
}
markReadCommand . GetParameter ( 1 ) . Value = isRead ;
transaction . Commit ( ) ;
foreach ( var id in notificationIdList )
}
{
catch ( OperationCanceledException )
markReadCommand . GetParameter ( 2 ) . Value = id ;
{
if ( transaction ! = null )
{
transaction . Rollback ( ) ;
}
throw ;
markReadCommand . Transaction = transaction ;
}
catch ( Exception e )
{
Logger . ErrorException ( "Failed to save notification:" , e ) ;
if ( transaction ! = null )
markReadCommand . ExecuteNonQuery ( ) ;
{
}
transaction . Rollback ( ) ;
}
throw ;
transaction . Commit ( ) ;
}
}
finally
catch ( OperationCanceledException )
{
{
if ( transaction ! = null )
if ( transaction ! = null )
{
{
transaction . Dispose ( ) ;
transaction . Rollback ( ) ;
}
}
WriteLock . Release ( ) ;
throw ;
}
}
}
catch ( Exception e )
{
Logger . ErrorException ( "Failed to save notification:" , e ) ;
protected override void CloseConnection ( )
if ( transaction ! = null )
{
{
if ( _connection ! = null )
transaction . Rollback ( ) ;
{
}
if ( _connection . IsOpen ( ) )
{
_connection . Close ( ) ;
}
_connection . Dispose ( ) ;
throw ;
_connection = null ;
}
finally
{
if ( transaction ! = null )
{
transaction . Dispose ( ) ;
}
}
}
}
}
}
}
}
}