mirror of https://github.com/Squidex/squidex.git
6 changed files with 0 additions and 315 deletions
@ -1,97 +0,0 @@ |
|||||
// ==========================================================================
|
|
||||
// GoogleCloudInvalidator.cs
|
|
||||
// Squidex Headless CMS
|
|
||||
// ==========================================================================
|
|
||||
// Copyright (c) Squidex Group
|
|
||||
// All rights reserved.
|
|
||||
// ==========================================================================
|
|
||||
|
|
||||
using System; |
|
||||
using System.Collections.Concurrent; |
|
||||
using Google.Cloud.PubSub.V1; |
|
||||
using Grpc.Core; |
|
||||
using Microsoft.Extensions.Logging; |
|
||||
|
|
||||
namespace Squidex.Infrastructure.GoogleCloud |
|
||||
{ |
|
||||
public class GoogleCloudPubSub : DisposableObject, IPubSub, IExternalSystem |
|
||||
{ |
|
||||
private readonly ProjectName projectName; |
|
||||
private readonly ILogger<GoogleCloudPubSub> logger; |
|
||||
private readonly ConcurrentDictionary<string, GoogleCloudSubscription> subscriptions = new ConcurrentDictionary<string, GoogleCloudSubscription>(); |
|
||||
private readonly PublisherClient publisher = PublisherClient.Create(); |
|
||||
|
|
||||
public GoogleCloudPubSub(ProjectName projectName, ILogger<GoogleCloudPubSub> logger) |
|
||||
{ |
|
||||
Guard.NotNull(projectName, nameof(projectName)); |
|
||||
Guard.NotNull(logger, nameof(logger)); |
|
||||
|
|
||||
this.projectName = projectName; |
|
||||
|
|
||||
this.logger = logger; |
|
||||
} |
|
||||
|
|
||||
protected override void DisposeObject(bool disposing) |
|
||||
{ |
|
||||
foreach (var subscription in subscriptions.Values) |
|
||||
{ |
|
||||
subscription.Dispose(); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
public void Connect() |
|
||||
{ |
|
||||
try |
|
||||
{ |
|
||||
try |
|
||||
{ |
|
||||
publisher.CreateTopic(new TopicName(projectName.ProjectId, "connection-test")); |
|
||||
} |
|
||||
catch (RpcException e) |
|
||||
{ |
|
||||
if (e.Status.StatusCode != StatusCode.AlreadyExists) |
|
||||
{ |
|
||||
throw; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
catch (Exception ex) |
|
||||
{ |
|
||||
throw new ConfigurationException($"GoogleCloud connection failed to connect to project {projectName.ProjectId}", ex); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
public void Publish(string channelName, string token, bool notifySelf) |
|
||||
{ |
|
||||
Guard.NotNull(channelName, nameof(channelName)); |
|
||||
|
|
||||
subscriptions.GetOrAdd(channelName, Create).Publish(token, notifySelf); |
|
||||
} |
|
||||
|
|
||||
public IDisposable Subscribe(string channelName, Action<string> handler) |
|
||||
{ |
|
||||
Guard.NotNull(channelName, nameof(channelName)); |
|
||||
|
|
||||
return subscriptions.GetOrAdd(channelName, Create).Subscribe(handler); |
|
||||
} |
|
||||
|
|
||||
private GoogleCloudSubscription Create(string channelName) |
|
||||
{ |
|
||||
var topicName = new TopicName(projectName.ProjectId, channelName); |
|
||||
|
|
||||
try |
|
||||
{ |
|
||||
publisher.CreateTopic(topicName); |
|
||||
} |
|
||||
catch (RpcException e) |
|
||||
{ |
|
||||
if (e.Status.StatusCode != StatusCode.AlreadyExists) |
|
||||
{ |
|
||||
throw; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
return new GoogleCloudSubscription(topicName, logger); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,135 +0,0 @@ |
|||||
// ==========================================================================
|
|
||||
// GoogleCloudSubscription.cs
|
|
||||
// Squidex Headless CMS
|
|
||||
// ==========================================================================
|
|
||||
// Copyright (c) Squidex Group
|
|
||||
// All rights reserved.
|
|
||||
// ==========================================================================
|
|
||||
|
|
||||
using System; |
|
||||
using System.Linq; |
|
||||
using System.Reactive.Subjects; |
|
||||
using System.Text; |
|
||||
using System.Threading; |
|
||||
using System.Threading.Tasks; |
|
||||
using Google.Cloud.PubSub.V1; |
|
||||
using Google.Protobuf; |
|
||||
using Grpc.Core; |
|
||||
using Microsoft.Extensions.Logging; |
|
||||
|
|
||||
// ReSharper disable InvertIf
|
|
||||
|
|
||||
namespace Squidex.Infrastructure.GoogleCloud |
|
||||
{ |
|
||||
public class GoogleCloudSubscription : DisposableObject |
|
||||
{ |
|
||||
private static readonly Guid InstanceId = Guid.NewGuid(); |
|
||||
private const string EmptyData = "Empty"; |
|
||||
private readonly Subject<string> subject = new Subject<string>(); |
|
||||
private readonly PublisherClient publisher = PublisherClient.Create(); |
|
||||
private readonly TopicName topicName; |
|
||||
private readonly ILogger<GoogleCloudPubSub> logger; |
|
||||
private readonly Task pullTask; |
|
||||
private readonly CancellationTokenSource completionToken = new CancellationTokenSource(); |
|
||||
|
|
||||
public GoogleCloudSubscription(TopicName topicName, ILogger<GoogleCloudPubSub> logger) |
|
||||
{ |
|
||||
this.topicName = topicName; |
|
||||
|
|
||||
this.logger = logger; |
|
||||
|
|
||||
pullTask = PullAsync(); |
|
||||
} |
|
||||
|
|
||||
protected override void DisposeObject(bool disposing) |
|
||||
{ |
|
||||
completionToken.Cancel(); |
|
||||
|
|
||||
pullTask.Wait(); |
|
||||
} |
|
||||
|
|
||||
public void Publish(string token, bool notifySelf) |
|
||||
{ |
|
||||
try |
|
||||
{ |
|
||||
if (string.IsNullOrWhiteSpace(token)) |
|
||||
{ |
|
||||
token = EmptyData; |
|
||||
} |
|
||||
|
|
||||
var message = new PubsubMessage |
|
||||
{ |
|
||||
Attributes = |
|
||||
{ |
|
||||
{ "Sender", (notifySelf ? Guid.Empty : InstanceId).ToString() } |
|
||||
}, |
|
||||
Data = ByteString.CopyFromUtf8(token) |
|
||||
}; |
|
||||
|
|
||||
publisher.Publish(topicName, new [] { message }); |
|
||||
} |
|
||||
catch (Exception ex) |
|
||||
{ |
|
||||
logger.LogError(InfrastructureErrors.InvalidatingReceivedFailed, ex, "Failed to send invalidation message {0}", token); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
private async Task PullAsync() |
|
||||
{ |
|
||||
var subscriber = SubscriberClient.Create(); |
|
||||
var subscriptionName = new SubscriptionName(topicName.ProjectId, "squidex-" + Guid.NewGuid()); |
|
||||
|
|
||||
await subscriber.CreateSubscriptionAsync(subscriptionName, topicName, null, 60); |
|
||||
|
|
||||
try |
|
||||
{ |
|
||||
while (!completionToken.IsCancellationRequested) |
|
||||
{ |
|
||||
try |
|
||||
{ |
|
||||
var response = await subscriber.PullAsync(subscriptionName, false, int.MaxValue, completionToken.Token); |
|
||||
|
|
||||
foreach (var receivedMessage in response.ReceivedMessages) |
|
||||
{ |
|
||||
var token = receivedMessage.Message.Data.ToString(Encoding.UTF8); |
|
||||
|
|
||||
Guid sender; |
|
||||
|
|
||||
if (!receivedMessage.Message.Attributes.ContainsKey("Sender") || !Guid.TryParse(receivedMessage.Message.Attributes["Sender"], out sender)) |
|
||||
{ |
|
||||
return; |
|
||||
} |
|
||||
|
|
||||
if (sender != InstanceId) |
|
||||
{ |
|
||||
subject.OnNext(token); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
await subscriber.AcknowledgeAsync(subscriptionName, response.ReceivedMessages.Select(m => m.AckId)); |
|
||||
} |
|
||||
catch (RpcException e) |
|
||||
{ |
|
||||
if (e.Status.StatusCode == StatusCode.DeadlineExceeded) |
|
||||
{ |
|
||||
continue; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
catch (TaskCanceledException) |
|
||||
{ |
|
||||
logger.LogWarning("Pull process has been cancelled."); |
|
||||
} |
|
||||
finally |
|
||||
{ |
|
||||
await subscriber.DeleteSubscriptionAsync(subscriptionName); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
public IDisposable Subscribe(Action<string> handler) |
|
||||
{ |
|
||||
return subject.Subscribe(handler); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -1,19 +0,0 @@ |
|||||
// ==========================================================================
|
|
||||
// InfrastructureErrors.cs
|
|
||||
// Squidex Headless CMS
|
|
||||
// ==========================================================================
|
|
||||
// Copyright (c) Squidex Group
|
|
||||
// All rights reserved.
|
|
||||
// ==========================================================================
|
|
||||
|
|
||||
using Microsoft.Extensions.Logging; |
|
||||
|
|
||||
namespace Squidex.Infrastructure.GoogleCloud |
|
||||
{ |
|
||||
public class InfrastructureErrors |
|
||||
{ |
|
||||
public static readonly EventId InvalidatingReceivedFailed = new EventId(40001, "InvalidingReceivedFailed"); |
|
||||
|
|
||||
public static readonly EventId InvalidatingPublishedFailed = new EventId(40002, "InvalidatingPublishedFailed"); |
|
||||
} |
|
||||
} |
|
||||
@ -1,19 +0,0 @@ |
|||||
using System.Reflection; |
|
||||
using System.Runtime.CompilerServices; |
|
||||
using System.Runtime.InteropServices; |
|
||||
|
|
||||
// General Information about an assembly is controlled through the following
|
|
||||
// set of attributes. Change these attribute values to modify the information
|
|
||||
// associated with an assembly.
|
|
||||
[assembly: AssemblyConfiguration("")] |
|
||||
[assembly: AssemblyCompany("")] |
|
||||
[assembly: AssemblyProduct("Squidex.Infrastructure.GoogleCloud")] |
|
||||
[assembly: AssemblyTrademark("")] |
|
||||
|
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
|
||||
// to COM components. If you need to access a type in this assembly from
|
|
||||
// COM, set the ComVisible attribute to true on that type.
|
|
||||
[assembly: ComVisible(false)] |
|
||||
|
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
|
||||
[assembly: Guid("4a80390e-507a-4477-8a10-be89a7427232")] |
|
||||
@ -1,21 +0,0 @@ |
|||||
<?xml version="1.0" encoding="utf-8"?> |
|
||||
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> |
|
||||
<PropertyGroup> |
|
||||
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion> |
|
||||
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath> |
|
||||
</PropertyGroup> |
|
||||
|
|
||||
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.Props" Condition="'$(VSToolsPath)' != ''" /> |
|
||||
<PropertyGroup Label="Globals"> |
|
||||
<ProjectGuid>4a80390e-507a-4477-8a10-be89a7427232</ProjectGuid> |
|
||||
<RootNamespace>Squidex.Infrastructure.GoogleCloud</RootNamespace> |
|
||||
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">.\obj</BaseIntermediateOutputPath> |
|
||||
<OutputPath Condition="'$(OutputPath)'=='' ">.\bin\</OutputPath> |
|
||||
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion> |
|
||||
</PropertyGroup> |
|
||||
|
|
||||
<PropertyGroup> |
|
||||
<SchemaVersion>2.0</SchemaVersion> |
|
||||
</PropertyGroup> |
|
||||
<Import Project="$(VSToolsPath)\DotNet\Microsoft.DotNet.targets" Condition="'$(VSToolsPath)' != ''" /> |
|
||||
</Project> |
|
||||
@ -1,24 +0,0 @@ |
|||||
{ |
|
||||
"version": "1.0.0-*", |
|
||||
"dependencies": { |
|
||||
"Google.Cloud.PubSub.V1": "1.0.0-beta06", |
|
||||
"Microsoft.Extensions.Caching.Abstractions": "1.1.0", |
|
||||
"Microsoft.Extensions.Logging": "1.1.0", |
|
||||
"Squidex.Infrastructure": "1.0.0-*", |
|
||||
"System.Linq": "4.3.0", |
|
||||
"System.Reactive": "3.1.1", |
|
||||
"System.Reflection.TypeExtensions": "4.3.0", |
|
||||
"System.Security.Claims": "4.3.0" |
|
||||
}, |
|
||||
"frameworks": { |
|
||||
"netstandard1.6": { |
|
||||
"dependencies": { |
|
||||
"NETStandard.Library": "1.6.1" |
|
||||
}, |
|
||||
"imports": "dnxcore50" |
|
||||
} |
|
||||
}, |
|
||||
"tooling": { |
|
||||
"defaultNamespace": "Squidex.Infrastructure.Redis" |
|
||||
} |
|
||||
} |
|
||||
Loading…
Reference in new issue