Ejemplo n.º 1
0
        /// <summary>
        /// Executes the target activity method.
        /// </summary>
        /// <param name="client">The associated Temporal client.</param>
        /// <param name="argBytes">The encoded activity arguments.</param>
        /// <returns>The encoded activity results.</returns>
        private async Task <byte[]> InvokeAsync(TemporalClient client, byte[] argBytes)
        {
            await SyncContext.Clear;

            var parameters     = activityMethod.GetParameters();
            var parameterTypes = new Type[parameters.Length];

            for (int i = 0; i < parameters.Length; i++)
            {
                parameterTypes[i] = parameters[i].ParameterType;
            }

            var resultType       = activityMethod.ReturnType;
            var args             = TemporalHelper.BytesToArgs(dataConverter, argBytes, parameterTypes);
            var serializedResult = Array.Empty <byte>();

            if (resultType.IsGenericType)
            {
                // Activity method returns: Task<T>

                var result = await NeonHelper.GetTaskResultAsObjectAsync((Task)activityMethod.Invoke(this, args));

                serializedResult = client.DataConverter.ToData(result);
            }
            else
            {
                // Activity method returns: Task

                await(Task) activityMethod.Invoke(this, args);
            }

            return(serializedResult);
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Default internal constructor.
        /// </summary>
        /// <param name="client">The associated client.</param>
        /// <param name="withinWorkflow">
        /// Optionally indicates that the stub was created from within a workflow and that
        /// operations such as get result, query, signal, and cancel must be performed
        /// within local activities such that that can be replayed from history correctly.
        /// </param>
        internal WorkflowStub(TemporalClient client, bool withinWorkflow = false)
        {
            Covenant.Requires <ArgumentNullException>(client != null, nameof(client));

            this.client         = client;
            this.withinWorkflow = withinWorkflow;
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Internal constructor.
        /// </summary>
        /// <param name="client">The parent client.</param>
        /// <param name="workerId">The ID of the worker as tracked by the <b>temporal-proxy</b>.</param>
        /// <param name="options">Specifies the worker options or <c>null</c>.</param>
        internal Worker(TemporalClient client, long workerId, WorkerOptions options)
        {
            Covenant.Requires <ArgumentNullException>(client != null, nameof(client));
            Covenant.Requires <ArgumentNullException>(options != null, nameof(options));

            this.Client   = client;
            this.WorkerId = workerId;
            this.options  = options;
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Internal constructor for use outside of a workflow.
        /// </summary>
        /// <param name="client">Specifies the associated client.</param>
        /// <param name="execution">Specifies the target workflow execution.</param>
        /// <param name="namespace">Optionally specifies the target namespace (defaults to the client's default namespace).</param>
        internal ExternalWorkflowStub(TemporalClient client, WorkflowExecution execution, string @namespace = null)
        {
            Covenant.Requires <ArgumentNullException>(client != null, nameof(client));
            Covenant.Requires <ArgumentNullException>(execution != null, nameof(execution));

            this.client     = client;
            this.@namespace = client.ResolveNamespace(@namespace);
            this.Execution  = execution;
        }
Ejemplo n.º 5
0
        /// <summary>
        /// Internal constructor.
        /// </summary>
        /// <param name="parentWorkflow">The parent workflow.</param>
        /// <param name="workflowTypeName">The workflow type name.</param>
        /// <param name="options">Optional child workflow options.</param>
        internal ChildWorkflowFutureStub(Workflow parentWorkflow, string workflowTypeName, ChildWorkflowOptions options = null)
        {
            Covenant.Requires <ArgumentNullException>(parentWorkflow != null, nameof(parentWorkflow));
            Covenant.Requires <ArgumentNullException>(!string.IsNullOrEmpty(workflowTypeName), nameof(workflowTypeName));

            this.parentWorkflow   = parentWorkflow;
            this.client           = parentWorkflow.Client;
            this.WorkflowTypeName = workflowTypeName;
            this.Options          = ChildWorkflowOptions.Normalize(client, options);
        }
Ejemplo n.º 6
0
        /// <summary>
        /// Internal constructor for use within a workflow.
        /// </summary>
        /// <param name="parentWorkflow">Specifies the parent workflow.</param>
        /// <param name="execution">Specifies the target workflow execution.</param>
        /// <param name="namespace">Optionally specifies the target namespace (defaults to the client's default namespace).</param>
        internal ExternalWorkflowStub(Workflow parentWorkflow, WorkflowExecution execution, string @namespace = null)
        {
            Covenant.Requires <ArgumentNullException>(parentWorkflow != null, nameof(parentWorkflow));
            Covenant.Requires <ArgumentNullException>(execution != null, nameof(execution));

            this.parentWorkflow = parentWorkflow;
            this.client         = parentWorkflow.Client;
            this.@namespace     = client.ResolveNamespace(@namespace);
            this.Execution      = execution;
        }
Ejemplo n.º 7
0
        /// <summary>
        /// Internal constructor.
        /// </summary>
        /// <param name="parentWorkflow">The associated parent workflow.</param>
        /// <param name="activityTypeName">
        /// Specifies the target activity type name.
        /// </param>
        /// <param name="options">The activity options or <c>null</c>.</param>
        internal ActivityFutureStub(Workflow parentWorkflow, string activityTypeName, ActivityOptions options = null)
        {
            Covenant.Requires <ArgumentNullException>(parentWorkflow != null, nameof(parentWorkflow));
            Covenant.Requires <ArgumentNullException>(!string.IsNullOrEmpty(activityTypeName), nameof(activityTypeName));

            this.parentWorkflow   = parentWorkflow;
            this.client           = parentWorkflow.Client;
            this.activityTypeName = activityTypeName;
            this.hasStarted       = false;
            this.options          = ActivityOptions.Normalize(client, options);
        }
Ejemplo n.º 8
0
        /// <summary>
        /// Internal constructor.
        /// </summary>
        /// <param name="client">The associated client.</param>
        /// <param name="parentWorkflow">Identifies the parent workflow.</param>
        /// <param name="activityTypeName">Specifies the target activity type name.</param>
        /// <param name="options">Optionally specifies custom activity options.</param>
        /// <remarks>
        /// <para>
        /// <paramref name="activityTypeName"/> specifies the target activity implementation type name and optionally,
        /// the specific activity method to be called for activity interfaces that have multiple methods.  For
        /// activity methods tagged by <c>ActivityMethod]</c>[ with specifying a name, the activity type name will default
        /// to the fully qualified interface type name or the custom type name specified by <see cref="ActivityAttribute.Name"/>.
        /// </para>
        /// <para>
        /// For activity methods with <see cref="ActivityMethodAttribute.Name"/> specified, the activity type will
        /// look like this by default:
        /// </para>
        /// <code>
        /// ACTIVITY-TYPE-NAME::METHOD-NAME
        /// </code>
        /// <note>
        /// You may need to customize activity type name when interoperating with activities written
        /// in other languages.  See <a href="https://doc.neonkube.com/Neon.Temporal-CrossPlatform.htm">Temporal Cross-Platform</a>
        /// for more information.
        /// </note>
        /// </remarks>
        internal ActivityStub(TemporalClient client, Workflow parentWorkflow, string activityTypeName, ActivityOptions options = null)
        {
            Covenant.Requires <ArgumentNullException>(client != null, nameof(client));
            Covenant.Requires <ArgumentNullException>(parentWorkflow != null, nameof(parentWorkflow));
            Covenant.Requires <ArgumentNullException>(!string.IsNullOrEmpty(activityTypeName), nameof(activityTypeName));

            this.client           = client;
            this.parentWorkflow   = parentWorkflow;
            this.activityTypeName = activityTypeName;
            this.options          = options;
        }
Ejemplo n.º 9
0
        /// <summary>
        /// Used to construct an untyped workflow stub that can be used to start an external workflow.
        /// </summary>
        /// <param name="client">The associated client.</param>
        /// <param name="workflowTypeName">The workflow type name.</param>
        /// <param name="execution">The workflow execution.</param>
        /// <param name="options">The workflow options.</param>
        internal WorkflowStub(TemporalClient client, string workflowTypeName, WorkflowExecution execution, StartWorkflowOptions options)
        {
            Covenant.Requires <ArgumentNullException>(client != null, nameof(client));
            Covenant.Requires <ArgumentNullException>(!string.IsNullOrEmpty(workflowTypeName), nameof(workflowTypeName));
            Covenant.Requires <ArgumentNullException>(execution != null, nameof(execution));
            Covenant.Requires <ArgumentNullException>(options != null, nameof(options));

            this.client           = client;
            this.WorkflowTypeName = workflowTypeName;
            this.Execution        = execution;
            this.Options          = options;
            this.withinWorkflow   = false;
        }
Ejemplo n.º 10
0
        /// <summary>
        /// Internal constructor.
        /// </summary>
        /// <param name="parentWorkflow">The parent workflow.</param>
        /// <param name="queueId">The queue ID.</param>
        /// <param name="capacity">The maximum number of items allowed in the queue.</param>
        /// <exception cref="NotSupportedException">Thrown when this is called outside of a workflow entry point method.</exception>
        /// <remarks>
        /// <note>
        /// <see cref="WorkflowQueue{T}"/> instances may only be created within
        /// workflow entry point methods.
        /// </note>
        /// </remarks>
        internal WorkflowQueue(Workflow parentWorkflow, long queueId, int capacity)
        {
            Covenant.Requires <ArgumentNullException>(parentWorkflow != null, nameof(parentWorkflow));
            Covenant.Requires <ArgumentException>(queueId > 0, nameof(queueId));
            Covenant.Requires <ArgumentException>(capacity >= 2, nameof(capacity));
            WorkflowBase.CheckCallContext(allowWorkflow: true);

            this.client    = parentWorkflow.Client;
            this.contextId = parentWorkflow.ContextId;
            this.Capacity  = capacity;
            this.queueId   = queueId;
            this.isClosed  = false;
        }
Ejemplo n.º 11
0
        /// <summary>
        /// Internal constructor.
        /// </summary>
        /// <param name="client">The associated client.</param>
        /// <param name="methodName">
        /// Optionally identifies the target workflow method by the name specified in
        /// the <c>[WorkflowMethod]</c> attribute tagging the method.  Pass a <c>null</c>
        /// or empty string to target the default method.
        /// </param>
        /// <param name="options">Optional workflow options.</param>
        internal WorkflowFutureStub(TemporalClient client, string methodName = null, StartWorkflowOptions options = null)
        {
            Covenant.Requires <ArgumentNullException>(client != null, nameof(client));

            var workflowInterface = typeof(WorkflowInterface);
            var method            = TemporalHelper.GetWorkflowMethod(workflowInterface, methodName);

            TemporalHelper.ValidateWorkflowInterface(workflowInterface);

            this.client           = client;
            this.workflowTypeName = TemporalHelper.GetWorkflowTarget(workflowInterface, methodName).WorkflowTypeName;
            this.options          = StartWorkflowOptions.Normalize(client, options, workflowInterface, method);
        }
Ejemplo n.º 12
0
        /// <summary>
        /// Internal constructor.
        /// </summary>
        /// <param name="parentWorkflow">The associated parent workflow.</param>
        /// <param name="methodName">
        /// Optionally identifies the target activity method by the name specified in
        /// the <c>[ActivityMethod]</c> attribute tagging the method.  Pass a <c>null</c>
        /// or empty string to target the default method.
        /// </param>
        /// <param name="options">The activity options or <c>null</c>.</param>
        internal ActivityFutureStub(Workflow parentWorkflow, string methodName = null, ActivityOptions options = null)
        {
            Covenant.Requires <ArgumentNullException>(parentWorkflow != null, nameof(parentWorkflow));

            var activityInterface = typeof(TActivityInterface);

            TemporalHelper.ValidateActivityInterface(activityInterface);

            this.parentWorkflow = parentWorkflow;
            this.client         = parentWorkflow.Client;
            this.hasStarted     = false;

            var activityTarget  = TemporalHelper.GetActivityTarget(activityInterface, methodName);
            var methodAttribute = activityTarget.MethodAttribute;

            this.activityTypeName = activityTarget.ActivityTypeName;
            this.targetMethod     = activityTarget.TargetMethod;
            this.options          = ActivityOptions.Normalize(client, options, typeof(TActivityInterface), activityTarget.TargetMethod);
        }
Ejemplo n.º 13
0
        //---------------------------------------------------------------------
        // Static members

        /// <summary>
        /// Normalizes the options passed by creating or cloning a new instance as
        /// required and filling unset properties using default client settings.
        /// </summary>
        /// <param name="client">The associated Temporal client.</param>
        /// <param name="options">The input options or <c>null</c>.</param>
        /// <returns>The normalized options.</returns>
        internal static LocalActivityOptions Normalize(TemporalClient client, LocalActivityOptions options)
        {
            Covenant.Requires <ArgumentNullException>(client != null, nameof(client));

            if (options == null)
            {
                options = new LocalActivityOptions();
            }
            else
            {
                options = options.Clone();
            }

            if (options.ScheduleToCloseTimeout <= TimeSpan.Zero)
            {
                options.ScheduleToCloseTimeout = client.Settings.ActivityScheduleToCloseTimeout;
            }

            return(options);
        }
Ejemplo n.º 14
0
        //---------------------------------------------------------------------
        // Static members

        /// <summary>
        /// <b>INTERNAL USE ONLY:</b> Normalizes the options passed by creating or cloning a new
        /// instance as required and filling unset properties using default client settings.
        /// </summary>
        /// <param name="client">The associated Temporal client.</param>
        /// <param name="options">The input options or <c>null</c>.</param>
        /// <param name="workflowInterface">Optionally specifies the workflow interface definition.</param>
        /// /// <param name="method">Optionally specifies the target workflow method.</param>
        /// <returns>The normalized options.</returns>
        /// <exception cref="ArgumentNullException">Thrown if a valid task queue is not specified.</exception>
        public static ChildWorkflowOptions Normalize(TemporalClient client, ChildWorkflowOptions options, Type workflowInterface = null, MethodInfo method = null)
        {
            Covenant.Requires <ArgumentNullException>(client != null, nameof(client));

            WorkflowInterfaceAttribute interfaceAttribute = null;
            WorkflowMethodAttribute    methodAttribute    = null;

            if (options == null)
            {
                options = new ChildWorkflowOptions();
            }
            else
            {
                options = options.Clone();
            }

            if (workflowInterface != null)
            {
                TemporalHelper.ValidateWorkflowInterface(workflowInterface);

                interfaceAttribute = workflowInterface.GetCustomAttribute <WorkflowInterfaceAttribute>();
            }

            if (method != null)
            {
                methodAttribute = method.GetCustomAttribute <WorkflowMethodAttribute>();
            }

            if (string.IsNullOrEmpty(options.Namespace))
            {
                if (!string.IsNullOrEmpty(methodAttribute?.Namespace))
                {
                    options.Namespace = methodAttribute.Namespace;
                }

                if (string.IsNullOrEmpty(options.Namespace) && !string.IsNullOrEmpty(interfaceAttribute?.Namespace))
                {
                    options.Namespace = interfaceAttribute.Namespace;
                }
            }

            if (string.IsNullOrEmpty(options.TaskQueue))
            {
                if (!string.IsNullOrEmpty(methodAttribute?.TaskQueue))
                {
                    options.TaskQueue = methodAttribute.TaskQueue;
                }

                if (string.IsNullOrEmpty(options.TaskQueue) && !string.IsNullOrEmpty(interfaceAttribute?.TaskQueue))
                {
                    options.TaskQueue = interfaceAttribute.TaskQueue;
                }

                if (string.IsNullOrEmpty(options.TaskQueue))
                {
                    options.TaskQueue = client.Settings.TaskQueue;
                }
            }

            if (options.WorkflowExecutionTimeout <= TimeSpan.Zero)
            {
                if (methodAttribute != null && methodAttribute.WorkflowExecutionTimeoutSeconds > 0)
                {
                    options.WorkflowExecutionTimeout = TimeSpan.FromSeconds(methodAttribute.WorkflowExecutionTimeoutSeconds);
                }

                if (options.WorkflowExecutionTimeout <= TimeSpan.Zero)
                {
                    options.WorkflowExecutionTimeout = client.Settings.WorkflowExecutionTimeout;
                }
            }

            if (options.WorkflowRunTimeout <= TimeSpan.Zero)
            {
                if (methodAttribute != null && methodAttribute.WorkflowRunTimeoutSeconds > 0)
                {
                    options.WorkflowRunTimeout = TimeSpan.FromSeconds(methodAttribute.WorkflowRunTimeoutSeconds);
                }

                if (options.WorkflowRunTimeout <= TimeSpan.Zero)
                {
                    options.WorkflowRunTimeout = client.Settings.WorkflowRunTimeout;
                }
            }

            if (options.WorkflowTaskTimeout <= TimeSpan.Zero)
            {
                if (methodAttribute != null && methodAttribute.WorkflowTaskTimeoutSeconds > 0)
                {
                    options.WorkflowTaskTimeout = TimeSpan.FromSeconds(methodAttribute.WorkflowTaskTimeoutSeconds);
                }

                if (options.WorkflowTaskTimeout <= TimeSpan.Zero)
                {
                    options.WorkflowTaskTimeout = client.Settings.WorkflowTaskTimeout;
                }
            }

            if (options.WorkflowIdReusePolicy == Temporal.WorkflowIdReusePolicy.UseDefault)
            {
                if (methodAttribute != null && methodAttribute.WorkflowIdReusePolicy != WorkflowIdReusePolicy.UseDefault)
                {
                    options.WorkflowIdReusePolicy = methodAttribute.WorkflowIdReusePolicy;
                }

                if (options.WorkflowIdReusePolicy == Temporal.WorkflowIdReusePolicy.UseDefault)
                {
                    options.WorkflowIdReusePolicy = client.Settings.WorkflowIdReusePolicy;
                }
            }

            return(options);
        }
Ejemplo n.º 15
0
 /// <summary>
 /// Constructor.
 /// </summary>
 /// <param name="client">The associated client.</param>
 /// <param name="execution">The workflow execution.</param>
 /// /// <param name="namespace">Optionally specifies the target namespace.  This defaults to the default client namespace.</param>
 internal ExternalWorkflowFuture(TemporalClient client, WorkflowExecution execution, string @namespace)
 {
     this.client     = client;
     this.Execution  = execution;
     this.@namespace = @namespace;
 }
Ejemplo n.º 16
0
        //---------------------------------------------------------------------
        // Static members

        /// <summary>
        /// Normalizes the options passed by creating or cloning a new instance as
        /// required and filling unset properties using default client settings.
        /// </summary>
        /// <param name="client">The associated Temporal client.</param>
        /// <param name="options">The input options or <c>null</c>.</param>
        /// <param name="workflowInterface">Optionally specifies the workflow interface definition.</param>
        /// /// <param name="method">Optionally specifies the target workflow method.</param>
        /// <returns>The normalized options.</returns>
        /// <exception cref="ArgumentNullException">Thrown if a valid task queue is not specified.</exception>
        internal static StartWorkflowOptions Normalize(TemporalClient client, StartWorkflowOptions options, Type workflowInterface = null, MethodInfo method = null)
        {
            Covenant.Requires <ArgumentNullException>(client != null, nameof(client));

            WorkflowInterfaceAttribute interfaceAttribute = null;
            WorkflowMethodAttribute    methodAttribute    = null;

            if (options == null)
            {
                options = new StartWorkflowOptions();
            }
            else
            {
                options = options.Clone();
            }

            if (workflowInterface != null)
            {
                TemporalHelper.ValidateWorkflowInterface(workflowInterface);

                interfaceAttribute = workflowInterface.GetCustomAttribute <WorkflowInterfaceAttribute>();
            }

            if (method != null)
            {
                methodAttribute = method.GetCustomAttribute <WorkflowMethodAttribute>();
            }

            if (string.IsNullOrEmpty(options.Namespace))
            {
                if (!string.IsNullOrEmpty(methodAttribute?.Namespace))
                {
                    options.Namespace = methodAttribute.Namespace;
                }

                if (string.IsNullOrEmpty(options.Namespace) && !string.IsNullOrEmpty(interfaceAttribute?.Namespace))
                {
                    options.Namespace = interfaceAttribute.Namespace;
                }

                if (string.IsNullOrEmpty(options.Namespace))
                {
                    options.Namespace = client.Settings.Namespace;
                }

                if (string.IsNullOrEmpty(options.Namespace))
                {
                    throw new ArgumentNullException(nameof(options), "You must specify a valid namnespace explicitly in [TemporalSettings], [ActivityOptions] or via an [ActivityInterface] or [ActivityMethod] attribute on the target activity interface or method.");
                }
            }

            if (string.IsNullOrEmpty(options.TaskQueue))
            {
                if (!string.IsNullOrEmpty(methodAttribute?.TaskQueue))
                {
                    options.TaskQueue = methodAttribute.TaskQueue;
                }

                if (string.IsNullOrEmpty(options.TaskQueue) && !string.IsNullOrEmpty(interfaceAttribute?.TaskQueue))
                {
                    options.TaskQueue = interfaceAttribute.TaskQueue;
                }

                if (string.IsNullOrEmpty(options.TaskQueue))
                {
                    options.TaskQueue = client.Settings.TaskQueue;
                }

                if (string.IsNullOrEmpty(options.TaskQueue))
                {
                    throw new ArgumentNullException(nameof(options), "You must specify a valid task queue explicitly via [StartWorkflowOptions] or using an [WorkflowInterface] or [WorkflowMethod] attribute on the target workflow interface or method.");
                }
            }

            if (options.WorkflowExecutionTimeout <= TimeSpan.Zero)
            {
                if (methodAttribute != null && methodAttribute.WorkflowExecutionTimeoutSeconds > 0)
                {
                    options.WorkflowExecutionTimeout = TimeSpan.FromSeconds(methodAttribute.WorkflowExecutionTimeoutSeconds);
                }

                if (options.WorkflowExecutionTimeout <= TimeSpan.Zero)
                {
                    options.WorkflowExecutionTimeout = client.Settings.WorkflowExecutionTimeout;
                }
            }

            if (options.WorkflowRunTimeout <= TimeSpan.Zero)
            {
                if (methodAttribute != null && methodAttribute.WorkflowRunTimeoutSeconds > 0)
                {
                    options.WorkflowRunTimeout = TimeSpan.FromSeconds(methodAttribute.WorkflowRunTimeoutSeconds);
                }

                if (options.WorkflowRunTimeout <= TimeSpan.Zero)
                {
                    options.WorkflowRunTimeout = client.Settings.WorkflowRunTimeout;
                }
            }

            if (options.WorkflowTaskTimeout <= TimeSpan.Zero)
            {
                if (methodAttribute != null && methodAttribute.WorkflowTaskTimeoutSeconds > 0)
                {
                    options.WorkflowTaskTimeout = TimeSpan.FromSeconds(methodAttribute.WorkflowTaskTimeoutSeconds);
                }

                if (options.WorkflowTaskTimeout <= TimeSpan.Zero)
                {
                    options.WorkflowTaskTimeout = client.Settings.WorkflowTaskTimeout;
                }
            }

            if (options.WorkflowIdReusePolicy == Temporal.WorkflowIdReusePolicy.UseDefault)
            {
                if (methodAttribute != null && methodAttribute.WorkflowIdReusePolicy != WorkflowIdReusePolicy.UseDefault)
                {
                    options.WorkflowIdReusePolicy = methodAttribute.WorkflowIdReusePolicy;
                }

                if (options.WorkflowIdReusePolicy == Temporal.WorkflowIdReusePolicy.UseDefault)
                {
                    options.WorkflowIdReusePolicy = client.Settings.WorkflowIdReusePolicy;
                }
            }

            if (string.IsNullOrEmpty(options.CronSchedule) && !string.IsNullOrEmpty(methodAttribute?.CronSchedule))
            {
                options.CronSchedule = methodAttribute.CronSchedule;
            }

            return(options);
        }
Ejemplo n.º 17
0
        //---------------------------------------------------------------------
        // Static members

        /// <summary>
        /// Normalizes the options passed by creating or cloning a new instance as
        /// required and filling unset properties using default client settings.
        /// </summary>
        /// <param name="client">The associated Temporal client.</param>
        /// <param name="options">The input options or <c>null</c>.</param>
        /// <param name="activityInterface">Optionally specifies the activity interface definition.</param>
        /// /// <param name="method">Optionally specifies the target workflow method.</param>
        /// <returns>The normalized options.</returns>
        /// <exception cref="ArgumentNullException">Thrown if a valid task queue is not specified.</exception>
        internal static ActivityOptions Normalize(TemporalClient client, ActivityOptions options, Type activityInterface = null, MethodInfo method = null)
        {
            Covenant.Requires <ArgumentNullException>(client != null, nameof(client));

            options = options ?? new ActivityOptions();

            ActivityInterfaceAttribute interfaceAttribute = null;
            ActivityMethodAttribute    methodAttribute    = null;

            if (activityInterface != null)
            {
                TemporalHelper.ValidateActivityInterface(activityInterface);

                interfaceAttribute = activityInterface.GetCustomAttribute <ActivityInterfaceAttribute>();
            }

            if (method != null)
            {
                methodAttribute = method.GetCustomAttribute <ActivityMethodAttribute>();
            }

            if (string.IsNullOrEmpty(options.Namespace))
            {
                if (!string.IsNullOrEmpty(methodAttribute?.Namespace))
                {
                    options.Namespace = methodAttribute.Namespace;
                }

                if (string.IsNullOrEmpty(options.Namespace) && !string.IsNullOrEmpty(interfaceAttribute?.Namespace))
                {
                    options.Namespace = interfaceAttribute.Namespace;
                }
            }

            if (string.IsNullOrEmpty(options.TaskQueue))
            {
                if (!string.IsNullOrEmpty(methodAttribute?.TaskQueue))
                {
                    options.TaskQueue = methodAttribute.TaskQueue;
                }

                if (string.IsNullOrEmpty(options.TaskQueue) && !string.IsNullOrEmpty(interfaceAttribute?.TaskQueue))
                {
                    options.TaskQueue = interfaceAttribute.TaskQueue;
                }
            }

            if (options.ScheduleToCloseTimeout <= TimeSpan.Zero)
            {
                if (methodAttribute != null && methodAttribute.ScheduleToCloseTimeoutSeconds > 0)
                {
                    options.ScheduleToCloseTimeout = TimeSpan.FromSeconds(methodAttribute.ScheduleToCloseTimeoutSeconds);
                }

                if (options.ScheduleToCloseTimeout <= TimeSpan.Zero)
                {
                    options.ScheduleToCloseTimeout = client.Settings.ActivityScheduleToCloseTimeout;
                }
            }

            if (options.ScheduleToStartTimeout <= TimeSpan.Zero)
            {
                if (methodAttribute != null && methodAttribute.ScheduleToStartTimeoutSeconds > 0)
                {
                    options.ScheduleToStartTimeout = TimeSpan.FromSeconds(methodAttribute.ScheduleToStartTimeoutSeconds);
                }

                if (options.ScheduleToStartTimeout <= TimeSpan.Zero)
                {
                    options.ScheduleToStartTimeout = client.Settings.ActivityScheduleToStartTimeout;
                }
            }

            if (options.StartToCloseTimeout <= TimeSpan.Zero)
            {
                if (methodAttribute != null && methodAttribute.StartToCloseTimeoutSeconds > 0)
                {
                    options.StartToCloseTimeout = TimeSpan.FromSeconds(methodAttribute.StartToCloseTimeoutSeconds);
                }

                if (options.StartToCloseTimeout <= TimeSpan.Zero)
                {
                    options.StartToCloseTimeout = client.Settings.ActivityStartToCloseTimeout;
                }
            }

            return(options);
        }