예제 #1
0
        /// <inheritdoc cref="SierraActor{T}" />
        public override async Task <VstsBuildDefinition> Add(VstsBuildDefinition model)
        {
            var templateDefinition = model.SourceCode.ProjectType == ProjectTypeEnum.WebApi
                ? _vstsConfiguration.WebApiBuildDefinitionTemplate
                : _vstsConfiguration.WebUIBuildDefinitionTemplate;

            //load template
            var template = await _buildHttpClient.GetDefinitionAsync(_vstsConfiguration.VstsTargetProjectId,
                                                                     templateDefinition.DefinitionId, templateDefinition.RevisionId);

            //customize the template
            template.Name          = model.ToString();
            template.Repository.Id = model.SourceCode.RepoVstsId.ToString();

            //push to vsts
            var vstsDefinition =
                await _buildHttpClient.CreateOrUpdateDefinition(template, _vstsConfiguration.VstsTargetProjectId);

            //update model
            model.UpdateWithVstsDefinition(vstsDefinition.Id);

            _bigBrother.Publish(new BuildDefinitionCreated {
                DefinitionName = vstsDefinition.Name
            });

            return(model);
        }
        /// <inheritdoc />
        public async Task <ILease> ReadByLeaseTypeAsync(string leaseType)
        {
            return(await _retryPolicy.ExecuteAsync(async() =>
            {
                try
                {
                    var query = _documentClient.CreateDocumentQuery <CosmosDbLease>(
                        UriFactory.CreateDocumentCollectionUri(_options.Value.Database, _options.Value.LeasesCollection),
                        new FeedOptions
                    {
                        ConsistencyLevel = _options.Value.ConsistencyLevel
                    })
                                .Where(so => so.LeaseType == leaseType)
                                .AsDocumentQuery();

                    var feedResponse = await query.ExecuteNextAsync <CosmosDbLease>();
                    return feedResponse.FirstOrDefault();
                }
                catch (Exception e)
                {
                    _telemetry.Publish(e.ToExceptionEvent());
                    throw;
                }
            }).ConfigureAwait(false));
        }
예제 #3
0
        private async Task DistributeToService(Service service, InflightMessage message, CancellationToken cancelToken)
        {
            //here we have to identify APIs - ultimately by name but naming is not consistent at the moment

            //single partition only
            var parts = await QueryManager.GetPartitionListAsync(service.ServiceName);

            if (parts.Count == 0 && IsNullOrWhiteSpace(parts.ContinuationToken))
            {
                return;
            }

            if (parts.Count > 1 || !IsNullOrWhiteSpace(parts.ContinuationToken)) //there is more than 1 partition
            {
                return;
            }

            var partition = parts.First();

            cancelToken.ThrowIfCancellationRequested();

            var replicas = await QueryManager.GetReplicaListAsync(partition.PartitionInformation.Id); //stateless service - so no secondary replicas

            if (replicas == null || replicas.Count == 0 || !replicas.All(r =>
                                                                         r.HealthState == HealthState.Ok ||
                                                                         r.HealthState == HealthState.Warning))
            {
                //all considered unhealthy, do not try to ping them even

                _bb?.Publish(GetServiceReplicaAlert(service, "No healthy replica found"));
                return;
            }

            await Task.WhenAll(replicas.Select(r => DistributeToReplica(service, r, message, cancelToken)));
        }
예제 #4
0
        public async Task <Guid> DoWork(string payload, string type)
        {
            // need to handle the possibility of the resources in the pool being all busy!

            try
            {
                var handlerId = _free.Value.First();
                var handle    = Guid.NewGuid();
                _free.Value.Remove(handlerId);
                _busy.Value.Add(
                    handle,
                    new MessageHook
                {
                    HandlerId = handlerId,
                    Type      = type
                });

                await StateManager.AddOrUpdateStateAsync(nameof(_free), _free.Value, (s, value) => value);

                await StateManager.AddOrUpdateStateAsync(nameof(_busy), _busy.Value, (s, value) => value);

                await ActorProxy.Create <IEventHandlerActor>(new ActorId(handlerId)).Handle(handle, payload, type);

                return(handle);
            }
            catch (Exception e)
            {
                _bigBrother.Publish(e.ToExceptionEvent());
                throw;
            }
        }
예제 #5
0
        /// <summary>
        /// add new release definition by cloning the template
        /// </summary>
        /// <param name="model">release definition model</param>
        /// <returns>updated release definition model</returns>
        public override async Task <VstsReleaseDefinition> Add(VstsReleaseDefinition model)
        {
            var templateConfig = model.BuildDefinition.SourceCode.ProjectType == ProjectTypeEnum.WebApi
                ? model.RingBased ? _vstsConfiguration.WebApiRingReleaseDefinitionTemplate : _vstsConfiguration.WebApiReleaseDefinitionTemplate
                : model.RingBased ? _vstsConfiguration.WebUIRingReleaseDefinitionTemplate : _vstsConfiguration.WebUIReleaseDefinitionTemplate;


            //create (or locate)
            var clone = await ClonePipeline(model, templateConfig);

            //customize
            if (!model.RingBased)
            {
                await CustomizeNonRingPipeline(model, clone);
            }
            else
            {
                CustomizeRingPipeline(model, clone);
            }

            //persist (or update)

            var vstsDef =
                await _releaseHttpClient.CreateOrResetDefinition(clone, _vstsConfiguration.VstsTargetProjectId);

            model.UpdateWithVstsReleaseDefinition(vstsDef.Id);

            _bigBrother.Publish(new ReleaseDefinitionCreated {
                DefinitionName = model.ToString()
            });

            return(model);
        }
예제 #6
0
        public override async Task <ResourceGroup> Add(ResourceGroup model)
        {
            var            azure = _azureFactory[model.Environment];
            IResourceGroup resourceGroup;

            if (await azure.ResourceGroups.ContainAsync(model.Name))
            {
                resourceGroup = await azure.ResourceGroups.GetByNameAsync(model.Name);
            }
            else
            {
                resourceGroup = await azure.ResourceGroups
                                .Define(model.Name)
                                .WithRegion(Region.EuropeNorth)
                                .CreateAsync();

                _bigBrother.Publish(new ResourceGroupCreated
                {
                    EnvironmentName   = model.Environment.ToString(),
                    RegionName        = resourceGroup.RegionName,
                    ResourceId        = resourceGroup.Id,
                    ResourceGroupName = resourceGroup.Name,
                });
            }

            model.State      = EntityStateEnum.Created;
            model.ResourceId = resourceGroup.Id;
            return(model);
        }
예제 #7
0
        private async Task <TimeSpan> OperationTelemetryHandler(Func <CancellationToken, Task <TimeSpan> > operation, CancellationToken token, [CallerMemberName] string memberName = "")
        {
            try
            {
                var operationEvent = new OperationTelemetryEvent(memberName);

                var result = await operation(token).ConfigureAwait(false);

                _telemetry.Publish(operationEvent);

                return(result);
            }
            catch (OperationCanceledException _)
            {
                _telemetry.Publish(new LeaseStoppedEvent(InstanceId, _options.Value.WorkerType, _options.Value.Priority));

                throw;
            }
            catch (Exception ex)
            {
                _timer.Dispose();

                _telemetry.Publish(new LeaseExceptionEvent(InstanceId, _options.Value.WorkerType, _options.Value.Priority,
                                                           ex.Message));

                throw new WorkerLeaseException(
                          $"An unhandled exception occurred executing operation [{memberName}]", ex);
            }
        }
예제 #8
0
        /// <summary>
        ///
        /// </summary>
        /// <typeparam name="TRequest"></typeparam>
        /// <param name="request"></param>
        /// <param name="metadata"></param>
        /// <returns></returns>
        public virtual async Task Call <TRequest>(TRequest request, IDictionary <string, object> metadata = null)
        {
            try
            {
                if (!(request is MessageData messageData))
                {
                    throw new Exception("injected wrong implementation");
                }

                //make a call to client identity provider
                if (WebhookConfig.AuthenticationConfig.Type != AuthenticationType.None)
                {
                    await AcquireTokenHandler.GetToken(_client);
                }

                var uri      = RequestBuilder.BuildUri(WebhookConfig, messageData.Payload);
                var httpVerb = RequestBuilder.SelectHttpVerb(WebhookConfig, messageData.Payload);
                var payload  = this.RequestBuilder.BuildPayload(this.WebhookConfig, messageData.Payload, metadata);

                void TelemetryEvent(string msg)
                {
                    BigBrother.Publish(new HttpClientFailure(messageData.Handle, messageData.Type, payload, msg));
                }

                var response = await _client.ExecuteAsJsonReliably(httpVerb, uri, payload, TelemetryEvent);

                BigBrother.Publish(new WebhookEvent(messageData.Handle, messageData.Type, $"Response status code {response.StatusCode}"));
            }
            catch (Exception e)
            {
                BigBrother.Publish(e.ToExceptionEvent());
                throw;
            }
        }
        /// <inheritdoc />
        public virtual async Task <string> GetTokenAsync(CancellationToken cancellationToken)
        {
            //get initial access token and refresh token
            if (OidcAuthenticationToken.AccessToken == null)
            {
                BigBrother.Publish(new ClientTokenRequest
                {
                    ClientId  = OidcAuthenticationConfig.ClientId,
                    Authority = OidcAuthenticationConfig.Uri,
                    Message   = "Token is null getting a new one."
                });

                await EnterSemaphore(cancellationToken, async() =>
                {
                    var httpClient = HttpClientFactory.Get(OidcAuthenticationConfig.Uri);
                    var response   = await GetTokenResponseAsync(httpClient, cancellationToken);
                    ReportTokenUpdateFailure(OidcAuthenticationConfig, response);
                    UpdateToken(response);

                    BigBrother.Publish(new ClientTokenRequest
                    {
                        ClientId  = OidcAuthenticationConfig.ClientId,
                        Authority = OidcAuthenticationConfig.Uri,
                        Message   = "Got a new token and updating the http client when token was null"
                    });
                });
            }
            else if (CheckExpired())
            {
                await EnterSemaphore(cancellationToken, async() =>
                {
                    if (CheckExpired())
                    {
                        var httpClient = HttpClientFactory.Get(OidcAuthenticationConfig.Uri);
                        var response   = await GetTokenResponseAsync(httpClient, cancellationToken);
                        ReportTokenUpdateFailure(OidcAuthenticationConfig, response);
                        UpdateToken(response);

                        BigBrother.Publish(new ClientTokenRequest
                        {
                            ClientId  = OidcAuthenticationConfig.ClientId,
                            Authority = OidcAuthenticationConfig.Uri,
                            Message   = "Refreshing token and updating the http client with new token"
                        });
                    }
                });
            }

            return($"Bearer {OidcAuthenticationToken.AccessToken}");
        }
예제 #10
0
        /// <summary>
        /// This method is called whenever an actor is activated.
        /// An actor is activated the first time any of its methods are invoked.
        /// </summary>
        protected override async Task OnActivateAsync()
        {
            _bigBrother.Publish(new ActorActivated(this));

            var names = (await StateManager.GetStateNamesAsync()).Take(1).ToList();

            if (names.Any())
            {
                _handleTimer = RegisterTimer(
                    InternalHandle,
                    names.FirstOrDefault(),
                    TimeSpan.FromMilliseconds(100),
                    TimeSpan.MaxValue);
            }
        }
예제 #11
0
        /// <inheritdoc />
        /// <summary>
        /// This is the main entry point for your service replica.
        /// This method executes when this replica of your service becomes primary and has write status.
        /// </summary>
        /// <param name="cancellationToken">Canceled when Service Fabric needs to shut down this service replica.</param>
        protected override async Task RunAsync(CancellationToken cancellationToken)
        {
            InitInflightQueue();
            while (true)
            {
                cancellationToken.ThrowIfCancellationRequested();

                try
                {
                    using (var tx = StateManager.CreateTransaction())
                    {
                        var message = await _inflightQueue.TryDequeueAsync(tx, cancellationToken);

                        if (message.HasValue)
                        {
                            await _clusterNotifier.DistributeToCluster(message.Value, cancellationToken,
                                                                       Context.CodePackageActivationContext.ApplicationName);
                        }

                        await tx.CommitAsync();
                    }
                }
                catch (OperationCanceledException) //cancellation requested
                {
                    throw;
                }
                catch (Exception e) //anything else
                {
                    _bigBrother.Publish(e.ToExceptionEvent());
                }

                await Task.Delay(WaitTimeBetweenLoop, cancellationToken);
            }
            // ReSharper disable once FunctionNeverReturns
        }
예제 #12
0
        /// <inheritdoc />
        public void Initialize(ITelemetry telemetry)
        {
            if (!(telemetry is RequestTelemetry requestTelemetry))
            {
                return;
            }
            if (_httpContextAccessor?.HttpContext?.Request == null)
            {
                return;
            }

            var request = _httpContextAccessor.HttpContext.Request;

            try
            {
                if (string.IsNullOrEmpty(requestTelemetry.ResponseCode))
                {
                    HandleIncomingRequest(request.Path.Value, requestTelemetry, request);
                }
                else
                {
                    HandleCompletedRequest(request.Path.Value, requestTelemetry, request);
                }
            }
            catch (Exception e)
            {
                _bigBrother.Publish(e.ToExceptionEvent());
            }
        }
예제 #13
0
        /// <summary>
        ///
        /// </summary>
        /// <typeparam name="TRequest"></typeparam>
        /// <param name="request"></param>
        /// <param name="metadata"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public virtual async Task CallAsync <TRequest>(TRequest request, IDictionary <string, object> metadata, CancellationToken cancellationToken)
        {
            try
            {
                if (!(request is MessageData messageData))
                {
                    throw new Exception("injected wrong implementation");
                }

                //todo refactor into a single call and a dto
                var uri             = RequestBuilder.BuildUri(WebhookConfig, messageData.Payload);
                var httpMethod      = RequestBuilder.SelectHttpMethod(WebhookConfig, messageData.Payload);
                var originalPayload = RequestBuilder.BuildPayload(WebhookConfig, messageData.Payload, metadata);
                var payload         = WebhookConfig.PayloadTransformation == PayloadContractTypeEnum.WrapperContract
                    ? WrapPayload(originalPayload, WebhookConfig, messageData)
                    : originalPayload;

                var config  = RequestBuilder.SelectWebhookConfig(WebhookConfig, messageData.Payload);
                var headers = RequestBuilder.GetHttpHeaders(WebhookConfig, messageData);
                var authenticationConfig = RequestBuilder.GetAuthenticationConfig(WebhookConfig, messageData.Payload);

                var httpClient = HttpClientFactory.Get(config);

                await AddAuthenticationHeaderAsync(cancellationToken, authenticationConfig, headers);

                var response = await httpClient.SendRequestReliablyAsync(httpMethod, uri, headers, payload, cancellationToken);

                await _requestLogger.LogAsync(httpClient, response, messageData, uri, httpMethod, headers);
            }
            catch (Exception e)
            {
                BigBrother.Publish(e.ToExceptionEvent());
                throw;
            }
        }
예제 #14
0
        public void EntryPoint_PushTimed()
        {
            IBigBrother bb = BigBrother.CreateDefault(DevKey, DevKey).DeveloperMode();

            bb.Publish(new TestTimedEvent());
            bb.Flush();
        }
예제 #15
0
        /// <inheridoc/>
        public override async Task <SourceCodeRepository> Add(SourceCodeRepository sourceCodeRepository)
        {
            //if fork not requested, look up the repo id
            if (!sourceCodeRepository.Fork)
            {
                var gitRepo = await _gitClient.LoadGitRepositoryIfExists(sourceCodeRepository.SourceRepositoryName);

                if (gitRepo == null)
                {
                    throw new ArgumentException(
                              $"Repository {sourceCodeRepository.SourceRepositoryName} does not exist",
                              nameof(SourceCodeRepository));
                }

                sourceCodeRepository.UpdateWithVstsRepo(gitRepo.Id);
                return(sourceCodeRepository);
            }

            //otherwise fork to a new repo
            var repo = await _gitClient.CreateForkIfNotExists(_vstsConfiguration.VstsCollectionId, _vstsConfiguration.VstsTargetProjectId, sourceCodeRepository);

            if (!repo.IsFork)
            {
                _bigBrother.Publish(new ForkRequestFailed
                {
                    ForkName = repo.Name,
                    Message  = $"Repository already exists but is not a fork"
                });
            }
            else
            {
                sourceCodeRepository.UpdateWithVstsRepo(repo.Id);

                _bigBrother.Publish(new ForkRequestSucceeded {
                    ForkName = repo.Name
                });
                return(sourceCodeRepository);
            }

            return(null);
        }
예제 #16
0
        protected override async Task OnActivateAsync()
        {
            try
            {
                _bigBrother.Publish(new ActorActivated(this));

                var inHandlers = await StateManager.TryGetStateAsync <Dictionary <Guid, string> >(nameof(_messagesInHandlers));

                if (inHandlers.HasValue)
                {
                    _messagesInHandlers = inHandlers;
                }
                else
                {
                    _messagesInHandlers = new ConditionalValue <Dictionary <Guid, string> >(true, new Dictionary <Guid, string>());
                    await StateManager.AddOrUpdateStateAsync(nameof(_messagesInHandlers), _messagesInHandlers.Value, (s, value) => value);
                }

                await SetupServiceBus();

                _receiver = new MessageReceiver(
                    _settings.ServiceBusConnectionString,
                    EntityNameHelper.FormatSubscriptionPath(TypeExtensions.GetEntityName(Id.GetStringId()), SubscriptionName),
                    ReceiveMode.PeekLock,
                    new RetryExponential(TimeSpan.FromMilliseconds(100), TimeSpan.FromMilliseconds(500), 3),
                    BatchSize);

                _poolTimer = new Timer(ReadEvents,
                                       null,
                                       TimeSpan.FromMilliseconds(1000),
                                       TimeSpan.FromMilliseconds(100));
            }
            catch (Exception e)
            {
                _bigBrother.Publish(e.ToExceptionEvent());
                throw;
            }

            await base.OnActivateAsync();
        }
예제 #17
0
        public async Task LogAsync(
            HttpClient httpClient,
            HttpResponseMessage response,
            MessageData messageData,
            Uri uri,
            HttpMethod httpMethod,
            WebHookHeaders headers
            )
        {
            _bigBrother.Publish(new WebhookEvent(
                                    messageData.EventHandlerActorId,
                                    messageData.Type,
                                    $"Response status code {response.StatusCode}",
                                    uri.AbsoluteUri,
                                    httpMethod,
                                    response.StatusCode,
                                    messageData.CorrelationId));

            //only log the failed requests in more depth, need to have a good think about this - debugging v privacy
            if (response.IsSuccessStatusCode)
            {
                return;
            }

            _bigBrother.Publish(new FailedWebHookEvent(
                                    httpClient.DefaultRequestHeaders.ToString(),
                                    response.Headers.ToString(),
                                    messageData.Payload ?? string.Empty,
                                    await GetPayloadAsync(response),
                                    messageData.EventHandlerActorId,
                                    messageData.Type,
                                    $"Response status code {response.StatusCode}",
                                    uri.AbsoluteUri,
                                    httpMethod,
                                    response.StatusCode,
                                    messageData.CorrelationId)
            {
                AuthToken = response.StatusCode == System.Net.HttpStatusCode.Unauthorized? headers?.RequestHeaders?[Constants.Headers.Authorization]: string.Empty
            });
        }
예제 #18
0
        public void EntryPoint_PushAnonymous()
        {
            IBigBrother bb = BigBrother.CreateDefault(DevKey, DevKey).DeveloperMode();

            bb.Publish(new
            {
                SomeStuff        = Lorem.GetSentence(),
                SomeMoreStuff    = Lorem.GetSentence(),
                AndEvenMoreStuff = Lorem.GetSentence()
            });

            bb.Flush();
        }
예제 #19
0
 private AsyncRetryPolicy CreateRetryPolicy()
 {
     return(Policy
            .Handle <DocumentClientException>(e => e.RetryAfter > TimeSpan.Zero)
            .WaitAndRetryAsync(5,
                               (count, exception, context) => ((DocumentClientException)exception).RetryAfter,
                               (exception, timeSpan, count, context) =>
     {
         _telemetry.Publish(new CosmosRetryEvent(timeSpan, count));
         return Task.CompletedTask;
     }
                               ));
 }
예제 #20
0
        public IActionResult Post([FromBody] Record value)
        {
            if (string.IsNullOrWhiteSpace(value.Name) || string.IsNullOrWhiteSpace(value.Address))
            {
                return(BadRequest());
            }

            var id = new Random().Next(ExistingRecordsRange + 1, 1000);

            _bb.Publish(new ValueAddedEvent(id));

            return(Created($"/api/values/{id}", id));
        }
예제 #21
0
        public void EntryPoint_PushException()
        {
            const string message = "KABOOM!!!";
            IBigBrother  bb      = BigBrother.CreateDefault(DevKey, DevKey).DeveloperMode();

            try
            {
                BlowUp(message);
            }
            catch (Exception ex)
            {
                bb.Publish(ex.ToExceptionEvent());
                bb.Flush();
            }
        }
예제 #22
0
        private async Task PrepareActorCall(HttpContext context, PathString remaining)
        {
            try
            {
                // as per rfc, this may contain charset (and indeed other parameters)
                if (!context.Request.ContentType.StartsWith("application/json", StringComparison.InvariantCultureIgnoreCase))
                {
                    throw new ActorCallFailedException("only the application/json content type is accepted");
                }

                var actorMethod = FindActorMethod(remaining);

                var jsonSerializedParameter = await ReadAsStringAsync(context.Request.Body);

                var parameterValue = JsonConvert.DeserializeObject(jsonSerializedParameter, actorMethod.Parameter.ParameterType);

                var actorId = context.Request.Query["actorId"];

                var result = await CallActor(actorId, actorMethod.InterfaceType, actorMethod.Method, parameterValue);

                if (result != null)
                {
                    context.Response.ContentType = "application/json";
                    var resultJson = JsonConvert.SerializeObject(result);
                    await context.Response.WriteAsync(resultJson);
                }
                else
                {
                    context.Response.StatusCode = (int)HttpStatusCode.NoContent;
                }
            }
            catch (Exception ex)
            {
                _bigBrother.Publish(ex.ToExceptionEvent());

                context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;

                var error = new
                {
                    errors = ListInnerExceptions(ex)
                             .Where(x => !(x is AggregateException ag && ag.InnerExceptions.Count == 1))
                             .Select(x => new { message = x.Message, type = x.GetType().FullName })
                };

                context.Response.ContentType = "application/json";
                await context.Response.WriteAsync(JsonConvert.SerializeObject(error));
            }
        }
예제 #23
0
        /// <summary>
        /// Handles exceptions by populating the response inside the <see cref="HttpContext"/> depending on
        ///     which type of exception is being handled.
        /// </summary>
        /// <param name="context">The HTTP-specific information about an individual HTTP request.</param>
        /// <param name="exception"></param>
        /// <returns>[ASYNC] <see cref="Task"/> future promise.</returns>
        /// <remarks>
        /// This method will unwrap any <see cref="AggregateException"/> until it finds a regular exception
        ///     and then process the regular exception through the pipeline.
        /// </remarks>
        internal virtual async Task HandleException(HttpContext context, Exception exception)
        {
            if (context.Response.HasStarted)
            {
                Bb.Publish(new ResponseAlreadyStartedExceptionEvent {
                    Exception = exception
                });
                return;
            }

            // Continuously unwrap AggregateException
            while (exception is AggregateException aex)
            {
                if (aex.InnerExceptions.Any())
                {
                    exception = aex.InnerExceptions.First();
                }
                else
                {
                    break;
                }
            }

            string result;

            context.Response.ContentType = "application/json";
            if (exception is BadRequestException badRequest)
            {
                result = JsonConvert.SerializeObject(badRequest.ToResponse());
                context.Response.StatusCode = (int)HttpStatusCode.BadRequest;
            }
            else
            {
                result = JsonConvert.SerializeObject(
                    new ErrorResponse
                {
#if DEBUG
                    Message    = exception.Message,
                    StackTrace = exception.StackTrace
#else
                    Message = "Sorry, but something bad happened!"
#endif
                });
예제 #24
0
        public async Task <IActionResult> Post([FromBody] JObject payload, string type)
        {
            var proxyFactory = new ServiceProxyFactory((c) => new FabricTransportActorRemotingClientFactory(
                                                           fabricTransportRemotingSettings: null,
                                                           callbackMessageHandler: c,
                                                           serializationProvider: new ServiceRemotingJsonSerializationProvider()));

            var service =
                proxyFactory.CreateServiceProxy <IBullfrogNotificationBackendService>(
                    new Uri("fabric:/ISummonNoobs/ISummonNoobsBackendService"), new ServicePartitionKey(1)); //TODO: review keying strategy

            await service.IngestMessage(type, payload);

            _bigBrother.Publish(new MessagedIngested {
                MessageType = type, Payload = payload.ToString()
            });

            return(Ok());
        }
예제 #25
0
 protected override async Task OnOpenAsync(ReplicaOpenMode openMode, CancellationToken cancellationToken)
 {
     _bigBrother.Publish(new ServiceActivatedEvent(Context, InFlightMessageCount));
     await base.OnOpenAsync(openMode, cancellationToken);
 }
예제 #26
0
        /// <inheritdoc />
        public async Task <ILease> AllocateLeaseAsync(Guid instanceId, CancellationToken token)
        {
            _telemetry.Publish(new LeaseAcquisitionEvent(instanceId, _options.Value.WorkerType,
                                                         _options.Value.Priority, $"Lease allocation started for instance {instanceId}"));

            var lease = await _leaseStore.ReadByLeaseTypeAsync(_options.Value.WorkerType).ConfigureAwait(false);

            if (lease?.LeasedUntil != null && lease.LeasedUntil.Value > ServerDateTime.UtcNow)
            {
                if (lease.InstanceId == instanceId)
                {
                    _telemetry.Publish(new LeaseAcquisitionEvent(instanceId, _options.Value.WorkerType,
                                                                 _options.Value.Priority, $"Existing lease reused: {GenerateLeaseInfo(lease)}"));

                    return(lease);
                }

                return(null);
            }

            await _leaseStore.AddLeaseRequestAsync(new LeaseRequest
            {
                LeaseType  = _options.Value.WorkerType,
                Priority   = _options.Value.Priority,
                InstanceId = instanceId,
                TimeToLive = 2 * _options.Value.ElectionDelay.Seconds
            }).ConfigureAwait(false);

            // backoff to allow other workers to add their lease request
            await Task.Delay(_options.Value.ElectionDelay, token);

            _telemetry.Publish(new LeaseAcquisitionEvent(instanceId, _options.Value.WorkerType,
                                                         _options.Value.Priority, $"Leader election starting"));

            var winnerInstanceId = await _leaseStore.SelectWinnerRequestAsync(_options.Value.WorkerType);

            if (!winnerInstanceId.HasValue)
            {
                //This should not happen normally
                _telemetry.Publish(new WinnerNotExistingEvent(instanceId, _options.Value.WorkerType));
                return(null);
            }

            if (winnerInstanceId != instanceId)
            {
                _telemetry.Publish(new LeaseAcquisitionEvent(instanceId, _options.Value.WorkerType,
                                                             _options.Value.Priority, $"Lease failed to be acquired after election. Winner instance is {winnerInstanceId.Value}."));
                return(null);
            }

            if (lease == null)
            {
                lease = new Lease
                {
                    LeaseType = _options.Value.WorkerType
                };
            }

            var now = ServerDateTime.UtcNow;

            lease.InstanceId  = instanceId;
            lease.Priority    = _options.Value.Priority;
            lease.Interval    = _slottedInterval.Calculate(now, _options.Value.LeaseInterval);
            lease.LeasedUntil = now.Add(lease.Interval.Value);
            var persistResult = await TryPersistLease(lease).ConfigureAwait(false);

            return(persistResult.Lease);
        }
예제 #27
0
        public override async Task <ManagedIdentity> Add(ManagedIdentity model)
        {
            // TODO: remove this custom error logging when a more generic solution is available
            var    stage          = "initialization";
            string subscriptionId = null;

            try
            {
                var azure = _azureFactory[model.Environment];
                subscriptionId = azure.SubscriptionId;

                stage = "resourceGroupValidation";
                var resourceGroup = await azure.ResourceGroups.GetByNameAsync(model.ResourceGroupName);

                stage = "identityFinding";
                var identities = await azure.Identities.ListByResourceGroupAsync(model.ResourceGroupName);

                var identity = identities.FirstOrDefault(x => x.Name == model.IdentityName);

                if (identity == null)
                {
                    stage    = "identityCreation";
                    identity = await azure.Identities
                               .Define(model.IdentityName)
                               .WithRegion(resourceGroup.RegionName)
                               .WithExistingResourceGroup(resourceGroup)
                               .CreateAsync();
                }

                model.IdentityId = identity.Id;

                stage = "scaleSetValidation";
                var scaleSets = await azure.VirtualMachineScaleSets.ListAsync();

                stage = "scaleSetIdentityAssignment";
                Task AssignIdentityToScaleSet(IVirtualMachineScaleSet scaleSet) =>
                GetActor <IScaleSetIdentityActor>(ScaleSetIdentityActor.ActorIdPrefix + scaleSet.Id)
                .Add(new ScaleSetIdentity
                {
                    Environment       = model.Environment,
                    ManagedIdentityId = identity.Id,
                });

                var scaleSetAssignmentTasks = scaleSets.Select(AssignIdentityToScaleSet);

                await Task.WhenAll(scaleSetAssignmentTasks);

                model.State = EntityStateEnum.Created;
                return(model);
            }
            catch (Exception e)
            {
                var errorEvent = new ManagedIdentityActorError(e)
                {
                    Stage             = stage,
                    SubscriptionId    = subscriptionId,
                    EnvironmentName   = model.Environment.ToString(),
                    IdentityName      = model.IdentityName,
                    ResourceGroupName = model.ResourceGroupName,
                };
                _bigBrother.Publish(errorEvent);
                throw;
            }
        }
예제 #28
0
        /// <summary>
        /// configure services to be used by the asp.net runtime
        /// </summary>
        /// <param name="services">service collection</param>
        /// <returns>service provider instance (Autofac provider)</returns>
        public IServiceProvider ConfigureServices(IServiceCollection services)
        {
            try
            {
                services.AddApplicationInsightsTelemetry(AppSettings.Telemetry.InstrumentationKey);
                ConfigureDatabase(services);
                services.AddCors(options =>
                {
                    options.AddPolicy("CorsPolicy",
                                      cpb => cpb
                                      .AllowAnyOrigin()
                                      .AllowAnyMethod()
                                      .AllowAnyHeader()
                                      .AllowCredentials());
                });

                services.AddMvc(options =>
                {
                    var policy = ScopePolicy.Create(AppSettings.ServiceConfigurationOptions.RequiredScopes.ToArray());
                    options.Filters.Add(new AuthorizeFilter(policy));
                });

                services.AddApiVersioning(
                    o =>
                {
                    o.ReportApiVersions = true;
                    o.AssumeDefaultVersionWhenUnspecified = true;
                    o.DefaultApiVersion = new ApiVersion(1, 0);
                });

                services.AddSwaggerGen(c =>
                {
                    c.IncludeXmlComments("WebApi.Template.xml");
                    c.DescribeAllEnumsAsStrings();
                    c.SwaggerDoc("v1", new Info {
                        Version = "1.0.0", Title = "WebApi.Template"
                    });
                    c.CustomSchemaIds(x => x.FullName);
                    c.AddSecurityDefinition("Bearer",
                                            new ApiKeyScheme
                    {
                        In          = "header",
                        Description = "Please insert JWT with Bearer into field",
                        Name        = "Authorization",
                        Type        = "apiKey"
                    });
                });

                services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddIdentityServerAuthentication(x =>
                {
                    x.ApiName              = AppSettings.ServiceConfigurationOptions.ApiName;
                    x.SupportedTokens      = SupportedTokens.Jwt;
                    x.RequireHttpsMetadata = AppSettings.ServiceConfigurationOptions.IsHttps;
                    x.Authority            = AppSettings.ServiceConfigurationOptions.Authority;
                    x.RequireHttpsMetadata = AppSettings.ServiceConfigurationOptions.IsHttps;
                    //TODO: this requires Eshopworld.Beatles.Security to be refactored
                    //x.AddJwtBearerEventsTelemetry(bb);
                });

                services.AddMvc().AddFluentValidation(fvc => fvc.RegisterValidatorsFromAssemblyContaining <NameAddressesValidator>());

                var builder = new ContainerBuilder();
                builder.Populate(services);
                builder.RegisterInstance(_bb).As <IBigBrother>().SingleInstance();
                builder.RegisterInstance(AppSettings).AsSelf().SingleInstance();

                // add additional services or modules into container here

                var container = builder.Build();
                return(new AutofacServiceProvider(container));
            }
            catch (Exception e)
            {
                _bb.Publish(e.ToBbEvent());
                throw;
            }
        }
예제 #29
0
        /// <summary>
        /// configure services to be used by the asp.net runtime
        /// </summary>
        /// <param name="services">service collection</param>
        /// <returns>service provider instance (Autofac provider)</returns>
        public IServiceProvider ConfigureServices(IServiceCollection services)
        {
            try
            {
                services.AddApplicationInsightsTelemetry(_telemetrySettings.InstrumentationKey);
                services.Configure <ServiceConfigurationOptions>(_configuration.GetSection("ServiceConfigurationOptions"));

                var serviceConfigurationOptions = services.BuildServiceProvider()
                                                  .GetService <IOptions <ServiceConfigurationOptions> >();

                services.AddMvc(options =>
                {
                    var filter =
#if (DEBUG)
                        new AllowAnonymousFilter();
#else
                        var policy = ScopePolicy.Create(serviceConfigurationOptions.Value.RequiredScopes.ToArray());
                    (IFilterMetadata) new AuthorizeFilter(policy) :
#endif

                    options.Filters.Add(filter);
                });
                services.AddApiVersioning();

                //Get XML documentation
                var path = Path.Combine(AppContext.BaseDirectory, $"{Assembly.GetExecutingAssembly().GetName().Name}.xml");

                //if not generated throw an event but it's not going to stop the app from starting
                if (!File.Exists(path))
                {
                    BigBrother.Write(new Exception("Swagger XML document has not been included in the project"));
                }
                else
                {
                    services.AddSwaggerGen(c =>
                    {
                        c.IncludeXmlComments(path);
                        c.DescribeAllEnumsAsStrings();
                        c.SwaggerDoc("v1", new OpenApiInfo {
                            Version = Assembly.GetExecutingAssembly().GetName().Version.ToString(), Title = "ISummonNoobs"
                        });
                        c.CustomSchemaIds(x => x.FullName);
                        c.AddSecurityDefinition("Bearer",
                                                new OpenApiSecurityScheme
                        {
                            In           = ParameterLocation.Header,
                            Description  = "Please insert JWT with Bearer into field",
                            Type         = UseOpenApiV2 ? SecuritySchemeType.ApiKey : SecuritySchemeType.Http,
                            Scheme       = "bearer",
                            BearerFormat = "JWT",
                        });

                        c.AddSecurityRequirement(new OpenApiSecurityRequirement
                        {
                            {
                                new OpenApiSecurityScheme
                                {
                                    Reference = new OpenApiReference {
                                        Type = ReferenceType.SecurityScheme, Id = "Bearer"
                                    },
                                },
                                new string[0]
                            }
                        });
                    });
                }

                services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddIdentityServerAuthentication(
                    x =>
                {
                    x.ApiName              = serviceConfigurationOptions.Value.ApiName;
                    x.ApiSecret            = serviceConfigurationOptions.Value.ApiSecret;
                    x.Authority            = serviceConfigurationOptions.Value.Authority;
                    x.RequireHttpsMetadata = serviceConfigurationOptions.Value.IsHttps;
                    //TODO: this requires Eshopworld.Beatles.Security to be refactored
                    //x.AddJwtBearerEventsTelemetry(bb);
                });

                var builder = new ContainerBuilder();
                builder.Populate(services);
                builder.RegisterInstance(_bb).As <IBigBrother>().SingleInstance();

                // add additional services or modules into container here

                var container = builder.Build();
                return(new AutofacServiceProvider(container));
            }
            catch (Exception e)
            {
                _bb.Publish(e.ToExceptionEvent());
                throw;
            }
        }
예제 #30
0
        /// <summary>
        /// This is the main entry point for your service replica.
        /// This method executes when this replica of your service becomes primary and has write status.
        /// </summary>
        /// <param name="cancellationToken">Canceled when Service Fabric needs to shut down this service replica.</param>
        protected override async Task RunAsync(CancellationToken cancellationToken)
        {
            // TODO: Check fabric node topology - if running below Bronze, set min and target replicas to 1 instead of 3

            try
            {
                var serviceList = (await _fabricClient.QueryManager.GetServiceListAsync(new Uri($"fabric:/{Constants.CaptainHookApplication.ApplicationName}")))
                                  .Select(s => s.ServiceName.AbsoluteUri)
                                  .ToList();

                if (!serviceList.Contains(ServiceNaming.EventHandlerServiceFullName))
                {
                    await _fabricClient.ServiceManager.CreateServiceAsync(
                        new StatefulServiceDescription
                    {
                        ApplicationName            = new Uri($"fabric:/{Constants.CaptainHookApplication.ApplicationName}"),
                        HasPersistedState          = true,
                        MinReplicaSetSize          = _defaultServiceSettings.DefaultMinReplicaSetSize,
                        TargetReplicaSetSize       = _defaultServiceSettings.DefaultTargetReplicaSetSize,
                        PartitionSchemeDescription = new UniformInt64RangePartitionSchemeDescription(10),
                        ServiceTypeName            = ServiceNaming.EventHandlerActorServiceType,
                        ServiceName          = new Uri(ServiceNaming.EventHandlerServiceFullName),
                        PlacementConstraints = _defaultServiceSettings.DefaultPlacementConstraints
                    },
                        TimeSpan.FromSeconds(30),
                        cancellationToken);
                }

                foreach (var @event in _eventHandlersConfig)
                {
                    foreach (var sub in @event.AllSubscribers)
                    {
                        sub.EventType = @event.Type;
                        if (cancellationToken.IsCancellationRequested)
                        {
                            return;
                        }

                        var readerServiceNameUri = ServiceNaming.EventReaderServiceFullUri(@event.Type, sub.SubscriberName, sub.DLQMode != null);
                        if (!serviceList.Contains(readerServiceNameUri))
                        {
                            await _fabricClient.ServiceManager.CreateServiceAsync(
                                new StatefulServiceDescription
                            {
                                ApplicationName            = new Uri($"fabric:/{Constants.CaptainHookApplication.ApplicationName}"),
                                HasPersistedState          = true,
                                MinReplicaSetSize          = _defaultServiceSettings.DefaultMinReplicaSetSize,
                                TargetReplicaSetSize       = _defaultServiceSettings.DefaultTargetReplicaSetSize,
                                PartitionSchemeDescription = new SingletonPartitionSchemeDescription(),
                                ServiceTypeName            = ServiceNaming.EventReaderServiceType,
                                ServiceName          = new Uri(readerServiceNameUri),
                                InitializationData   = Encoding.UTF8.GetBytes(EventReaderInitData.GetReaderInitDataAsString(sub)),
                                PlacementConstraints = _defaultServiceSettings.DefaultPlacementConstraints
                            },
                                TimeSpan.FromSeconds(30),
                                cancellationToken);
                        }
                    }
                }


                // TODO: Can't do this for internal eshopworld.com|net hosts, otherwise the sharding would be crazy - need to aggregate internal hosts by domain
                //var uniqueHosts = Rules.Select(r => new Uri(r.HookUri).Host).Distinct();
                //var dispatcherServiceList = (await FabricClient.QueryManager.GetServiceListAsync(new Uri($"fabric:/{Constants.CaptainHookApplication.ApplicationName}")))
                //                        .Select(s => s.ServiceName.AbsoluteUri)
                //                        .ToList();

                //todo this might be used for dispatchers per host but that seems a bit drastic
                //foreach (var host in uniqueHosts)
                //{
                //    if (cancellationToken.IsCancellationRequested) return;

                //    var dispatcherServiceNameUri = $"fabric:/{Constants.CaptainHookApplication.ApplicationName}/{Constants.CaptainHookApplication.EventDispatcherServiceName}.{host}";
                //    if (dispatcherServiceList.Contains(dispatcherServiceNameUri)) continue;

                //    await FabricClient.ServiceManager.CreateServiceAsync(
                //        new StatefulServiceDescription
                //        {
                //            ApplicationName = new Uri($"fabric:/{Constants.CaptainHookApplication.ApplicationName}"),
                //            HasPersistedState = true,
                //            DefaultMinReplicaSetSize = 3,
                //            TargetReplicaSetSize = 3,
                //            PartitionSchemeDescription = new SingletonPartitionSchemeDescription(),
                //            ServiceTypeName = Constants.CaptainHookApplication.EventReaderServiceType,
                //            ServiceName = new Uri(dispatcherServiceNameUri),
                //            InitializationData = Encoding.UTF8.GetBytes(host)
                //        });
                //}
            }
            catch (Exception ex)
            {
                _bigBrother.Publish(ex.ToExceptionEvent());
                throw;
            }
        }