Skip to main content
Tweeted twitter.com/StackCodeReview/status/1012572944990687233
edited body
Source Link
Manolis
  • 343
  • 1
  • 8

The story here is about a console application that replays to a test system string clauses already imported in the production system to a test system.

The story here is about a console application that replays string clauses already imported in the production system to a test system.

The story here is about a console application that replays to a test system string clauses already imported in the production system.

Source Link
Manolis
  • 343
  • 1
  • 8

From production to staging

The story here is about a console application that replays string clauses already imported in the production system to a test system.

Looking forward to your comments.

namespace MyCompany.Department.ProjectXYZ;
{
    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using System.ServiceModel;
    using MyCompany.XYZ;

    /// <summary>
    /// Books message clauses to staging Diamant via web service.<para/>
    /// If no arguments are provided, the program reads from the production database log table (<see cref="ImportJobData"/>) 
    /// all clauses that were imported in the last 24 hours.<para/>
    /// If a single filename argument is provided, the program reads clauses from that file.<para/>
    /// The program writes clauses that encounter an error on booking to Diamant in a text file in the FailedClauses directory.
    /// </summary>
    public class Program
    {
        /// <summary>
        /// Client to the staging web service.
        /// </summary>
        private static ImportVSMessageClient _client;

        /// <summary>
        /// Error messages for all processed clauses.
        /// </summary>
        private static readonly List<string> _errorMessages = new List<String>();

        private static readonly IApplicationLogger _logger = ApplicationMonitoring.GetLogger(typeof(Program));

        private static readonly Lazy<ErrorService> _errorService = new Lazy<ErrorService>(() => new ErrorService());

        internal static void Main(string[] args)
        {
            WebServiceClientApplication.Initialize();

            _client = new ImportVSMessageClient();

            try
            {
                var clauses = GetClausesToImport(args);
                DoImport(clauses);
            }
            catch (Exception ex)
            {
                _errorMessages.Add(ex.Message);
            }
            finally
            {
                if (_errorMessages.Any())
                {
                    _errorService.Value.ProcessError(
                        "WebService.Client - Error",
                        string.Join(Environment.NewLine, _errorMessages));
                }

                _client.Close();
            }
        }

        #region Private methods

        private static IEnumerable<string> GetClausesToImport(string[] args)
        {
            if (!args.Any())
            {
                return GetImportedClausesOnPreviousDay();
            }

            string filename = args[0];
            return File.ReadAllLines(filename);
        }

        private static IEnumerable<string> GetImportedClausesOnPreviousDay()
        {
            IImportJobsService importJobsService = new ImportJobsService();

            return importJobsService.Load(DiamantSystem.Produktion, DateTime.Now.AddDays(-1), DateTime.Now)
                .Where(IsValid).OrderBy(ijd => ijd.Erstelldatum)
                .Select(ijd => ijd.Eingangswerte);
        }

        private static Boolean IsValid(ImportJobData ijd)
        {
            return ijd.Status == VerarbeitungsStatus.ImportErfolgreich && ijd.Satzart != Satzart.LOGOUT;
        }

        private static void DoImport(IEnumerable<string> clauses)
        {
            var clausesList = clauses.ToList();

            if (clausesList.Any())
            {
                _logger.Info("Importing {0} messages.", clausesList.Count);
                ImportClauses(clausesList);

                _logger.Info("Closing connection.");
                ImportClause(Satzart.LOGOUT);

                _logger.Info("Finished importing.");
            }
            else
            {
                _logger.Info("Nothing to import.");
            }
        }

        private static void ImportClauses(IEnumerable<string> clauses)
        {
            var failedClauses = new List<String>();

            foreach (var clause in clauses)
            {
                var success = ImportClause(clause);

                if (!success)
                {
                    failedClauses.Add(clause);
                }
            }

            if (failedClauses.Any())
            {
                WriteFailedClauses(failedClauses);
            }
        }

        // Returns true when successful.
        private static bool ImportClause(String clause)
        {
            var errorMessage = RunImportAction(() => _client.ImportMessage(clause));
            if (string.IsNullOrEmpty(errorMessage))
            {
                return true;
            }

            LogError(string.Format("Clause: {0}", clause));
            LogError(string.Format("Error: {0}", errorMessage));
            return false;
        }

        private static void LogError(string errorMsg)
        {
            _errorMessages.Add(errorMsg);
            _logger.Error(errorMsg);
        }

        // Returns empty string when successful, otherwise the error message.
        private static String RunImportAction(Action action)
        {
            try
            {
                action();
                return string.Empty;
            }
            catch (FaultException<DiamantWarningFaultContract> faultException)
            {
                return faultException.Detail.ErrorMessage.Aggregate((a, b) => a + Environment.NewLine + b);
            }
            catch (FaultException<DiamantFatalFaultContract> faultException)
            {
                return faultException.Detail.ErrorMessage.Aggregate((a, b) => a + Environment.NewLine + b);
            }
            catch (FaultException exception)
            {
                return string.Format("Code: {0}, Message: {1}", exception.Code.Name, exception.Message);
            }
            catch (Exception exception)
            {
                return exception.Message;
            }
        }

        private static void WriteFailedClauses(IEnumerable<string> failedClauses)
        {
            string filename = String.Format("FailedClauses_{0}.txt", DateTime.Now.ToString("yyyy-MM-dd-HHmmss"));
            filename = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "FailedClauses", filename);

            File.WriteAllLines(filename, failedClauses);
        }

        #endregion
    }
}