/// <summary>
        /// Handles the receipt of a response message coming from a remote platform by resuming the workflow run and handing the
        /// messages to the relevant CAST activity implementation.
        /// </summary>
        /// <param name="request">The original request message.</param>
        /// <param name="response">The response message to process.</param>
        public async void Process(TRequest request, TResponse response)
        {
            using (new DeferredChannelMessageContext())
                using (CastService.GetCastContext())
                {
                    try
                    {
                        var run = EntityRepository.Get <WorkflowRun>(request.RunId, WorkflowRunPreload);
                        if (run == null)
                        {
                            throw new Exception(string.Format("CAST workflow activity could not resume. Workflow run ({0}) not found.", request.RunId));
                        }

                        // let the workflow or caching or whatever, catch up before officially responding to RabbitMQ
                        if (run.RunStepCounter <= request.RunStep)
                        {
                            var state = await WaitForRunStep(run.Id, request.RunStep);

                            if (state < request.RunStep)
                            {
                                throw new Exception(string.Format("CAST workflow activity could not resume. Workflow run ({0}) wasn't in step.", request.RunId));
                            }
                        }

                        var castEvent = new CastActivityResponseEvent <TRequest, TResponse>(request, response);

                        WorkflowRunner.ResumeWorkflowAsync(run, castEvent);
                    }
                    catch (Exception err)
                    {
                        EventLog.Application.WriteError("Failed to process CAST response. {0}", err);
                    }
                }
        }
Beispiel #2
0
        /// <summary>
        /// Performs a simple write to the event log.
        /// </summary>
        /// <param name="logRequest">The log request.</param>
        /// <returns>The response to the request.</returns>
        public LogResponse Log(LogRequest logRequest)
        {
            using (Profiler.Measure("CastActivityService.Log"))
            {
                var response = new LogResponse();

                try
                {
                    if (logRequest == null)
                    {
                        throw new ArgumentNullException("logRequest");
                    }

                    if (!CastService.GetIsCastConfigured())
                    {
                        throw new InvalidOperationException();
                    }

                    EventLog.Application.WriteInformation(logRequest.Message);
                    response.Time = DateTime.UtcNow;
                }
                catch (Exception e)
                {
                    response.IsError = true;
                    response.Error   = e.Message;
                }

                return(response);
            }
        }
Beispiel #3
0
        /// <summary>
        /// Carries out an operation on a <see cref="UserAccount"/> within a tenant identified by the request.
        /// </summary>
        /// <param name="userRequest">The request.</param>
        /// <returns>The response.</returns>
        public UserInfoResponse UserOperation(UserOperationRequest userRequest)
        {
            using (Profiler.Measure("CastActivityService.UserOperation"))
            {
                var response = new UserInfoResponse
                {
                    Users = new UserList()
                };

                try
                {
                    if (userRequest == null)
                    {
                        throw new ArgumentNullException("userRequest");
                    }

                    if (!CastService.GetIsCastConfigured())
                    {
                        throw new InvalidOperationException();
                    }

                    var name   = userRequest.User;
                    var tenant = userRequest.Tenant;

                    switch (userRequest.Operation)
                    {
                    case Operation.Create:
                        UserService.Create(name, userRequest.Password, tenant, userRequest.Roles);
                        break;

                    case Operation.Delete:
                        UserService.Delete(name, tenant);
                        break;

                    default:
                        throw new NotSupportedException(userRequest.Operation.ToString());
                    }

                    if (userRequest.Operation != Operation.Delete)
                    {
                        var u = UserService.GetUser(name, tenant);
                        if (u != null)
                        {
                            response.Users.Add(u);
                        }
                    }
                }
                catch (Exception e)
                {
                    response.IsError = true;
                    response.Error   = e.Message;
                }

                return(response);
            }
        }
Beispiel #4
0
        /// <summary>
        /// Handles the receipt of a heartbeat message.
        /// </summary>
        /// <param name="pi">The platform information received.</param>
        private void HandleHeartbeat(RemotePlatformInfo pi)
        {
            if (!CastService.GetIsCastConfigured() || !CastService.GetIsCastServer())
            {
                return;
            }

            using (new DeferredChannelMessageContext())
                using (CastService.GetCastContext())
                    using (CastService.GetCastUser())
                    {
                        PlatformService.CreateOrUpdate(pi);
                    }
        }
Beispiel #5
0
        /// <summary>
        /// Carries out an operation on an <see cref="App"/> with respect to the tenant identified by the request.
        /// </summary>
        /// <param name="appRequest">The request.</param>
        /// <returns>The response.</returns>
        public ApplicationInfoResponse ApplicationOperation(ApplicationOperationRequest appRequest)
        {
            using (Profiler.Measure("CastActivityService.ApplicationOperation"))
            {
                var response = new ApplicationInfoResponse();

                try
                {
                    if (appRequest == null)
                    {
                        throw new ArgumentNullException("appRequest");
                    }

                    if (!CastService.GetIsCastConfigured())
                    {
                        throw new InvalidOperationException();
                    }

                    var tenant = appRequest.Tenant;

                    switch (appRequest.Operation)
                    {
                    case Contracts.ApplicationOperation.Install:
                        ApplicationService.Install(tenant, appRequest.Id, appRequest.Version);
                        break;

                    case Contracts.ApplicationOperation.Uninstall:
                        ApplicationService.Uninstall(tenant, appRequest.Id);
                        break;

                    default:
                        throw new NotSupportedException(appRequest.Operation.ToString());
                    }

                    var apps = ApplicationService.GetInstalledApps(tenant);
                    if (apps != null)
                    {
                        response.Installed = apps.ToList();
                    }
                }
                catch (Exception e)
                {
                    response.IsError = true;
                    response.Error   = e.Message;
                }

                return(response);
            }
        }
Beispiel #6
0
        /// <summary>
        /// Starts a timer which will send a heartbeat message every hour.
        /// </summary>
        private void StartHeartbeat()
        {
            var castConfiguration = ConfigurationSettings.GetCastConfigurationSection();

            if (castConfiguration == null)
            {
                return;
            }

            var castSettings = castConfiguration.Cast;

            if (castSettings == null)
            {
                return;
            }

            if (castSettings.Enabled != true)
            {
                return;
            }

            var interval = castConfiguration.Cast.Heartbeat;

            if (interval < 0)
            {
                interval = 60;
            }

            EventLog.Application.WriteInformation("Sending heartbeat every {0} minutes.", interval);
            //CastService.SendHeartbeat();

            _timer.Interval = interval * 1000 * 60;
            _timer.Elapsed += (s, a) =>
            {
                try
                {
                    EventLog.Application.WriteInformation("Sending heartbeat.");
                    CastService.SendHeartbeat();
                }
                catch (Exception ex)
                {
                    EventLog.Application.WriteError("Unexpected failure starting CAST heartbeat on timer. {0}", ex);
                }
            };
            _timer.Start();
        }
Beispiel #7
0
        /// <summary>
        /// Starts CAST communication channels.
        /// </summary>
        public void Start()
        {
            if (CastService.GetIsCastConfigured())
            {
                EventLog.Application.WriteWarning("CAST communications are starting.");

                // Server specific
                if (CastService.GetIsCastServer())
                {
                    HeartbeatListener.Receive <RemotePlatformInfo>(SpecialStrings.CastHeartbeatKey, HandleHeartbeat, false);
                }

                SendHeartbeatNowListener.Subscribe <string>(SpecialStrings.CastHeartbeatDemandKey, SendHeartbeatNow);
                StartHeartbeat();

                ClientListener.Respond <CastRequest, CastResponse>(CastService.GetClientCommunicationKey(), HandleRequest);
            }
        }
Beispiel #8
0
        /// <summary>
        /// Handles a CAST request received, passing on to the appropriate CAST activities service call.
        /// </summary>
        /// <param name="request">The request object received.</param>
        /// <returns>The response to pass back to the CAST Server.</returns>
        private CastResponse HandleRequest(CastRequest request)
        {
            // direct the appropriate requests to the activity service (TODO: some kind of registration would be nice)
            if (request == null)
            {
                throw new ArgumentNullException("request");
            }

            if (CastService.GetIsCastConfigured())
            {
                using (new DeferredChannelMessageContext())
                {
                    // Log
                    var logRequest = request as LogRequest;
                    if (logRequest != null)
                    {
                        return(CastActivityService.Log(logRequest));
                    }

                    // Tenant
                    var tenantRequest = request as TenantOperationRequest;
                    if (tenantRequest != null)
                    {
                        return(CastActivityService.TenantOperation(tenantRequest));
                    }

                    // User
                    var userRequest = request as UserOperationRequest;
                    if (userRequest != null)
                    {
                        return(CastActivityService.UserOperation(userRequest));
                    }

                    // Application
                    var appRequest = request as ApplicationOperationRequest;
                    if (appRequest != null)
                    {
                        return(CastActivityService.ApplicationOperation(appRequest));
                    }
                }
            }

            return(default(CastResponse));
        }
Beispiel #9
0
 /// <summary>
 /// Sends a heartbeat message immediately.
 /// </summary>
 /// <param name="request">The request received.</param>
 private void SendHeartbeatNow(string request)
 {
     EventLog.Application.WriteInformation("Sending heartbeat by request ({0})", request);
     CastService.SendHeartbeat();
 }
Beispiel #10
0
        /// <summary>
        /// Carries out an operation on a <see cref="Tenant"/> on this plaform identified by the request.
        /// </summary>
        /// <param name="tenantRequest">The request.</param>
        /// <returns>The response.</returns>
        public TenantInfoResponse TenantOperation(TenantOperationRequest tenantRequest)
        {
            using (Profiler.Measure("CastActivityService.TenantOperation"))
            {
                var response = new TenantInfoResponse
                {
                    Tenants = new TenantList()
                };

                try
                {
                    if (tenantRequest == null)
                    {
                        throw new ArgumentNullException("tenantRequest");
                    }

                    if (string.IsNullOrEmpty(tenantRequest.Name))
                    {
                        throw new ArgumentException("Tenant name may not be empty.");
                    }

                    if (!CastService.GetIsCastConfigured())
                    {
                        throw new InvalidOperationException();
                    }

                    var name = tenantRequest.Name;

                    switch (tenantRequest.Operation)
                    {
                    case Operation.Create:
                        TenantService.Create(name);
                        break;

                    case Operation.Delete:
                        TenantService.Delete(name);
                        break;

                    case Operation.Enable:
                        TenantService.Enable(name);
                        break;

                    case Operation.Disable:
                        TenantService.Disable(name);
                        break;

                    case Operation.Rename:
                        TenantService.Rename(tenantRequest.Id, tenantRequest.Name);
                        break;

                    default:
                        throw new NotSupportedException(tenantRequest.Operation.ToString());
                    }

                    if (tenantRequest.Operation != Operation.Delete)
                    {
                        var ti = TenantService.GetTenant(name);
                        if (ti != null)
                        {
                            response.Tenants.Add(ti);
                        }
                    }
                }
                catch (Exception e)
                {
                    response.IsError = true;
                    response.Error   = e.Message;
                }

                return(response);
            }
        }