Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
CAP
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
tsai
CAP
Commits
327ef56f
Commit
327ef56f
authored
Aug 24, 2018
by
Savorboard
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
use Diagnostics event feature to send the message after transaction commited for Sql Server.
parent
3f37a453
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
169 additions
and
35 deletions
+169
-35
CAP.SqlServerCapOptionsExtension.cs
...NetCore.CAP.SqlServer/CAP.SqlServerCapOptionsExtension.cs
+2
-0
DiagnosticObserver.cs
...otNetCore.CAP.SqlServer/Diagnostics/DiagnosticObserver.cs
+65
-0
DiagnosticProcessorObserver.cs
....CAP.SqlServer/Diagnostics/DiagnosticProcessorObserver.cs
+38
-0
ICapTransaction.SqlServer.cs
src/DotNetCore.CAP.SqlServer/ICapTransaction.SqlServer.cs
+48
-26
IStorage.SqlServer.cs
src/DotNetCore.CAP.SqlServer/IStorage.SqlServer.cs
+8
-1
IStorageTransaction.SqlServer.cs
...DotNetCore.CAP.SqlServer/IStorageTransaction.SqlServer.cs
+2
-6
DatabaseTestHost.cs
test/DotNetCore.CAP.SqlServer.Test/DatabaseTestHost.cs
+6
-2
No files found.
src/DotNetCore.CAP.SqlServer/CAP.SqlServerCapOptionsExtension.cs
View file @
327ef56f
...
...
@@ -4,6 +4,7 @@
using
System
;
using
DotNetCore.CAP.Processor
;
using
DotNetCore.CAP.SqlServer
;
using
DotNetCore.CAP.SqlServer.Diagnostics
;
using
Microsoft.EntityFrameworkCore
;
using
Microsoft.Extensions.DependencyInjection
;
...
...
@@ -22,6 +23,7 @@ namespace DotNetCore.CAP
public
void
AddServices
(
IServiceCollection
services
)
{
services
.
AddSingleton
<
CapDatabaseStorageMarkerService
>();
services
.
AddSingleton
<
DiagnosticProcessorObserver
>();
services
.
AddSingleton
<
IStorage
,
SqlServerStorage
>();
services
.
AddSingleton
<
IStorageConnection
,
SqlServerStorageConnection
>();
...
...
src/DotNetCore.CAP.SqlServer/Diagnostics/DiagnosticObserver.cs
0 → 100644
View file @
327ef56f
using
System
;
using
System.Collections.Concurrent
;
using
System.Collections.Generic
;
using
System.Data.SqlClient
;
using
System.Reflection
;
using
DotNetCore.CAP.Models
;
namespace
DotNetCore.CAP.SqlServer.Diagnostics
{
internal
class
DiagnosticObserver
:
IObserver
<
KeyValuePair
<
string
,
object
>>
{
private
readonly
IDispatcher
_dispatcher
;
private
readonly
ConcurrentDictionary
<
Guid
,
List
<
CapPublishedMessage
>>
_bufferList
;
public
DiagnosticObserver
(
IDispatcher
dispatcher
,
ConcurrentDictionary
<
Guid
,
List
<
CapPublishedMessage
>>
bufferList
)
{
_dispatcher
=
dispatcher
;
_bufferList
=
bufferList
;
}
private
const
string
SqlClientPrefix
=
"System.Data.SqlClient."
;
public
const
string
SqlAfterCommitTransaction
=
SqlClientPrefix
+
"WriteTransactionCommitAfter"
;
public
const
string
SqlErrorCommitTransaction
=
SqlClientPrefix
+
"WriteTransactionCommitError"
;
public
void
OnCompleted
()
{
}
public
void
OnError
(
Exception
error
)
{
}
public
void
OnNext
(
KeyValuePair
<
string
,
object
>
evt
)
{
if
(
evt
.
Key
==
SqlAfterCommitTransaction
)
{
var
sqlConnection
=
(
SqlConnection
)
GetProperty
(
evt
.
Value
,
"Connection"
);
var
transactionKey
=
sqlConnection
.
ClientConnectionId
;
if
(
_bufferList
.
TryRemove
(
transactionKey
,
out
var
msgList
))
{
foreach
(
var
message
in
msgList
)
{
_dispatcher
.
EnqueueToPublish
(
message
);
}
}
}
else
if
(
evt
.
Key
==
SqlErrorCommitTransaction
)
{
var
sqlConnection
=
(
SqlConnection
)
GetProperty
(
evt
.
Value
,
"Connection"
);
var
transactionKey
=
sqlConnection
.
ClientConnectionId
;
_bufferList
.
TryRemove
(
transactionKey
,
out
_
);
}
}
static
object
GetProperty
(
object
_this
,
string
propertyName
)
{
return
_this
.
GetType
().
GetTypeInfo
().
GetDeclaredProperty
(
propertyName
)?.
GetValue
(
_this
);
}
}
}
\ No newline at end of file
src/DotNetCore.CAP.SqlServer/Diagnostics/DiagnosticProcessorObserver.cs
0 → 100644
View file @
327ef56f
using
System
;
using
System.Collections.Concurrent
;
using
System.Collections.Generic
;
using
System.Diagnostics
;
using
DotNetCore.CAP.Models
;
namespace
DotNetCore.CAP.SqlServer.Diagnostics
{
public
class
DiagnosticProcessorObserver
:
IObserver
<
DiagnosticListener
>
{
private
readonly
IDispatcher
_dispatcher
;
public
const
string
DiagnosticListenerName
=
"SqlClientDiagnosticListener"
;
public
ConcurrentDictionary
<
Guid
,
List
<
CapPublishedMessage
>>
BufferList
{
get
;
}
public
DiagnosticProcessorObserver
(
IDispatcher
dispatcher
)
{
_dispatcher
=
dispatcher
;
BufferList
=
new
ConcurrentDictionary
<
Guid
,
List
<
CapPublishedMessage
>>();
}
public
void
OnCompleted
()
{
}
public
void
OnError
(
Exception
error
)
{
}
public
void
OnNext
(
DiagnosticListener
listener
)
{
if
(
listener
.
Name
==
DiagnosticListenerName
)
{
listener
.
Subscribe
(
new
DiagnosticObserver
(
_dispatcher
,
BufferList
));
}
}
}
}
\ No newline at end of file
src/DotNetCore.CAP.SqlServer/ICapTransaction.SqlServer.cs
View file @
327ef56f
// Copyright (c) .NET Core Community. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
using
System
;
using
System.Collections.Generic
;
using
System.Data
;
using
System.Diagnostics
;
using
System.Data.SqlClient
;
using
DotNetCore.CAP.Models
;
using
DotNetCore.CAP.SqlServer.Diagnostics
;
using
Microsoft.EntityFrameworkCore.Infrastructure
;
using
Microsoft.EntityFrameworkCore.Storage
;
...
...
@@ -11,50 +15,68 @@ namespace DotNetCore.CAP
{
public
class
SqlServerCapTransaction
:
CapTransactionBase
{
public
SqlServerCapTransaction
(
IDispatcher
dispatcher
)
:
base
(
dispatcher
)
private
readonly
DiagnosticProcessorObserver
_diagnosticProcessor
;
public
SqlServerCapTransaction
(
IDispatcher
dispatcher
,
DiagnosticProcessorObserver
diagnosticProcessor
)
:
base
(
dispatcher
)
{
_diagnosticProcessor
=
diagnosticProcessor
;
}
p
ublic
override
void
Commit
(
)
p
rotected
override
void
AddToSent
(
CapPublishedMessage
msg
)
{
Debug
.
Assert
(
DbTransaction
!=
null
);
switch
(
DbTransaction
)
var
transactionKey
=
((
SqlConnection
)((
IDbTransaction
)
DbTransaction
).
Connection
).
ClientConnectionId
;
if
(
_diagnosticProcessor
.
BufferList
.
TryGetValue
(
transactionKey
,
out
var
list
))
{
case
IDbTransaction
dbTransaction
:
dbTransaction
.
Commit
();
break
;
case
IDbContextTransaction
dbContextTransaction
:
dbContextTransaction
.
Commit
();
break
;
list
.
Add
(
msg
);
}
else
{
var
msgList
=
new
List
<
CapPublishedMessage
>(
1
)
{
msg
};
_diagnosticProcessor
.
BufferList
.
TryAdd
(
transactionKey
,
msgList
);
}
}
Flush
();
public
override
void
Commit
()
{
throw
new
NotImplementedException
();
}
public
override
void
Rollback
()
{
Debug
.
Assert
(
DbTransaction
!=
null
);
switch
(
DbTransaction
)
{
case
IDbTransaction
dbTransaction
:
dbTransaction
.
Rollback
();
break
;
case
IDbContextTransaction
dbContextTransaction
:
dbContextTransaction
.
Rollback
();
break
;
}
throw
new
NotImplementedException
();
}
public
override
void
Dispose
()
{
(
DbTransaction
as
IDbTransaction
)?.
Dispose
();
}
}
public
static
class
CapTransactionExtensions
{
public
static
ICapTransaction
Begin
(
this
ICapTransaction
transaction
,
IDbTransaction
dbTransaction
,
bool
autoCommit
=
false
)
{
transaction
.
DbTransaction
=
dbTransaction
;
transaction
.
AutoCommit
=
autoCommit
;
return
transaction
;
}
public
static
IDbTransaction
BeginTransaction
(
this
IDbConnection
dbConnection
,
ICapPublisher
publisher
,
bool
autoCommit
=
false
)
{
if
(
dbConnection
.
State
==
ConnectionState
.
Closed
)
{
dbConnection
.
Open
();
}
var
dbTransaction
=
dbConnection
.
BeginTransaction
();
var
capTransaction
=
publisher
.
Transaction
.
Begin
(
dbTransaction
,
autoCommit
);
return
(
IDbTransaction
)
capTransaction
.
DbTransaction
;
}
public
static
ICapTransaction
Begin
(
this
ICapTransaction
transaction
,
IDbContextTransaction
dbTransaction
,
bool
autoCommit
=
false
)
{
...
...
@@ -64,7 +86,7 @@ namespace DotNetCore.CAP
return
transaction
;
}
public
static
IDbContextTransaction
Begin
AndJoinTo
Transaction
(
this
DatabaseFacade
database
,
public
static
IDbContextTransaction
BeginTransaction
(
this
DatabaseFacade
database
,
ICapPublisher
publisher
,
bool
autoCommit
=
false
)
{
var
trans
=
database
.
BeginTransaction
();
...
...
src/DotNetCore.CAP.SqlServer/IStorage.SqlServer.cs
View file @
327ef56f
...
...
@@ -4,10 +4,12 @@
using
System
;
using
System.Data
;
using
System.Data.SqlClient
;
using
System.Diagnostics
;
using
System.Threading
;
using
System.Threading.Tasks
;
using
Dapper
;
using
DotNetCore.CAP.Dashboard
;
using
DotNetCore.CAP.SqlServer.Diagnostics
;
using
Microsoft.Extensions.Logging
;
namespace
DotNetCore.CAP.SqlServer
...
...
@@ -18,12 +20,15 @@ namespace DotNetCore.CAP.SqlServer
private
readonly
IDbConnection
_existingConnection
=
null
;
private
readonly
ILogger
_logger
;
private
readonly
SqlServerOptions
_options
;
private
readonly
DiagnosticProcessorObserver
_diagnosticProcessorObserver
;
public
SqlServerStorage
(
ILogger
<
SqlServerStorage
>
logger
,
CapOptions
capOptions
,
SqlServerOptions
options
)
SqlServerOptions
options
,
DiagnosticProcessorObserver
diagnosticProcessorObserver
)
{
_options
=
options
;
_diagnosticProcessorObserver
=
diagnosticProcessorObserver
;
_logger
=
logger
;
_capOptions
=
capOptions
;
}
...
...
@@ -53,6 +58,8 @@ namespace DotNetCore.CAP.SqlServer
}
_logger
.
LogDebug
(
"Ensuring all create database tables script are applied."
);
DiagnosticListener
.
AllListeners
.
Subscribe
(
_diagnosticProcessorObserver
);
}
protected
virtual
string
CreateDbTablesScript
(
string
schema
)
...
...
src/DotNetCore.CAP.SqlServer/IStorageTransaction.SqlServer.cs
View file @
327ef56f
...
...
@@ -14,7 +14,6 @@ namespace DotNetCore.CAP.SqlServer
{
private
readonly
IDbConnection
_dbConnection
;
private
readonly
IDbTransaction
_dbTransaction
;
private
readonly
string
_schema
;
public
SqlServerStorageTransaction
(
SqlServerStorageConnection
connection
)
...
...
@@ -24,7 +23,6 @@ namespace DotNetCore.CAP.SqlServer
_dbConnection
=
new
SqlConnection
(
options
.
ConnectionString
);
_dbConnection
.
Open
();
_dbTransaction
=
_dbConnection
.
BeginTransaction
(
IsolationLevel
.
ReadCommitted
);
}
public
void
UpdateMessage
(
CapPublishedMessage
message
)
...
...
@@ -36,7 +34,7 @@ namespace DotNetCore.CAP.SqlServer
var
sql
=
$"UPDATE [
{
_schema
}
].[Published] SET [Retries] = @Retries,[Content] = @Content,[ExpiresAt] = @ExpiresAt,[StatusName]=@StatusName WHERE Id=@Id;"
;
_dbConnection
.
Execute
(
sql
,
message
,
_dbTransaction
);
_dbConnection
.
Execute
(
sql
,
message
);
}
public
void
UpdateMessage
(
CapReceivedMessage
message
)
...
...
@@ -48,18 +46,16 @@ namespace DotNetCore.CAP.SqlServer
var
sql
=
$"UPDATE [
{
_schema
}
].[Received] SET [Retries] = @Retries,[Content] = @Content,[ExpiresAt] = @ExpiresAt,[StatusName]=@StatusName WHERE Id=@Id;"
;
_dbConnection
.
Execute
(
sql
,
message
,
_dbTransaction
);
_dbConnection
.
Execute
(
sql
,
message
);
}
public
Task
CommitAsync
()
{
_dbTransaction
.
Commit
();
return
Task
.
CompletedTask
;
}
public
void
Dispose
()
{
_dbTransaction
.
Dispose
();
_dbConnection
.
Dispose
();
}
}
...
...
test/DotNetCore.CAP.SqlServer.Test/DatabaseTestHost.cs
View file @
327ef56f
...
...
@@ -2,16 +2,18 @@ using System;
using
System.Data
;
using
System.Data.SqlClient
;
using
Dapper
;
using
DotNetCore.CAP.SqlServer.Diagnostics
;
using
Microsoft.Extensions.Logging
;
using
Moq
;
namespace
DotNetCore.CAP.SqlServer.Test
{
public
abstract
class
DatabaseTestHost
:
IDisposable
public
abstract
class
DatabaseTestHost
:
IDisposable
{
protected
ILogger
<
SqlServerStorage
>
Logger
;
protected
CapOptions
CapOptions
;
protected
SqlServerOptions
SqlSeverOptions
;
protected
DiagnosticProcessorObserver
DiagnosticProcessorObserver
;
public
bool
SqlObjectInstalled
;
...
...
@@ -23,6 +25,8 @@ namespace DotNetCore.CAP.SqlServer.Test
.
SetupProperty
(
x
=>
x
.
ConnectionString
,
ConnectionUtil
.
GetConnectionString
())
.
Object
;
DiagnosticProcessorObserver
=
new
Mock
<
DiagnosticProcessorObserver
>().
Object
;
InitializeDatabase
();
}
...
...
@@ -42,7 +46,7 @@ IF NOT EXISTS (SELECT * FROM sysdatabases WHERE name = N'{databaseName}')
CREATE DATABASE [
{
databaseName
}
];"
);
}
new
SqlServerStorage
(
Logger
,
CapOptions
,
SqlSeverOptions
).
InitializeAsync
().
GetAwaiter
().
GetResult
();
new
SqlServerStorage
(
Logger
,
CapOptions
,
SqlSeverOptions
,
DiagnosticProcessorObserver
).
InitializeAsync
().
GetAwaiter
().
GetResult
();
SqlObjectInstalled
=
true
;
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment