/// <summary> /// Executes the communication package. /// </summary> /// <param name="communicationPackage">The communication package to execute.</param> /// <returns> /// <c>true</c> if execution succeeded; otherwise, <c>false</c> /// </returns> public override bool ExecutePackage(ICommunicationPackage communicationPackage) { SessionManager.VolatileElements.DeferredTransactionId = communicationPackage.XmlData.DeferredTransactionId; SessionManager.VolatileElements.LocalTransactionId = this.LocalTransactionId; try { XDocument commPkg = XDocument.Parse(communicationPackage.XmlData.Content); // paczka nie dojdzie do oddzialu z ktorego przyszla wiec nie ma potrzeby sprawdzania // czy przenoszony stan nalezy do magazynu lokalnego //XDocument warehoues = XDocument.Parse("<root/>"); //warehoues.Root.Add(from entry in commPkg.Root.Element("warehouseStock").Elements("entry") // select entry.Element("warehouseId")); //var localWarehouses = this.repository.FindLocalWarehouses(warehoues).Root.Elements("warehouse") // .Where(wh => wh.Element("isLocal").Value.Equals("true", StringComparison.OrdinalIgnoreCase)) // .Select(wh => new Guid(wh.Element("warehouseId").Value)); //foreach (XElement entry in commPkg.Root.Element("warehouseStock").Elements("entry")) //{ // if (localWarehouses.Contains(new Guid(entry.Element("warehouseId").Value)) == true) entry.Remove(); //} //if (commPkg.Root.Element("warehouseStock").Elements("entry").Count() > 0) this.repository.UpdateStock(commPkg); return(true); } catch (SqlException e) { this.Log.Error("WarehouseStockScript:ExecutePackage " + e.ToString()); return(false); } }
/// <summary> /// Sends specified communication package. /// </summary> /// <param name="xml">The comunication package.</param> /// <param name="isLastPackage">if set to <c>true</c> it's last package in transaction.</param> /// <returns><c>true</c> if send is successful; otherwise, <c>false</c>.</returns> private bool SendPackage(ICommunicationPackage xml, bool isLastPackage) { xml.Compress(); try { RoboFramework.Tools.RandomLogHelper.GetLog().Debug("PackageSender.cs - SendPackage(ICommunicationPackage xml, bool isLastPackage)"); Message result = CommunicationServiceProxy.Instance.SendData( SynchronizationHelper.CreateMessage( new SendDataParameters { Xml = xml.XmlData, IsLastInTransaction = isLastPackage, DepartmentIdentifier = xml.DatabaseId.Value }, "SendData", CommunicationServiceProxy.ProxyFactory.Endpoint.Binding.MessageVersion)); SendDataResponse response = SynchronizationHelper.GetData <SendDataResponse>(result); if (response == null) { return(false); } if (response.AdditionalData != null && response.AdditionalData.UndeliveredPackagesQuantity != null) { Manager.Receiver.WaitingPackages = response.AdditionalData.UndeliveredPackagesQuantity.Value; } return(response.Result); } catch (MessageSecurityException mse) { Log.Info("WCF MessageSecurityException"); Log.Info(mse.ToString()); Log.Info("================================================================="); try { CommunicationServiceProxy.ProxyFactory.Close(); } catch { try { CommunicationServiceProxy.ProxyFactory.Abort(); } catch { } } throw; } catch (TimeoutException e) { Log.Error(e.ToString(), true); // TODO -1 change to false when we will have a general view often this happens. return(false); } catch (System.ServiceModel.CommunicationException e) { Log.Error(e.ToString()); return(false); } }
/// <summary> /// Executes the communication package. /// </summary> /// <param name="communicationPackage">The communication package to execute.</param> /// <returns> /// <c>true</c> if execution succeeded; otherwise, <c>false</c> /// </returns> public override bool ExecutePackage(ICommunicationPackage communicationPackage) { try { using (var wrapper = this.UnitOfWork.ConnectionManager.SynchronizeConnection()) { SqlConnectionManager.Instance.SetConnection(wrapper.Connection, this.UnitOfWork.Transaction as SqlTransaction); } XDocument commPkg = XDocument.Parse(communicationPackage.XmlData.Content); SessionManager.VolatileElements.DeferredTransactionId = communicationPackage.XmlData.DeferredTransactionId; SessionManager.VolatileElements.LocalTransactionId = this.LocalTransactionId; this.ExecutionController.ExecuteCommand(() => UpdateDocumentStatus(commPkg)); return(true); } catch (SqlException e) { if (e.Number == 50012) // Conflict detection { throw new ConflictException("Conflict detected."); } else { this.Log.Error("ShiftDocumentStatusScript:ExecutePackage " + e.ToString()); return(false); } } }
/// <summary> /// Sends group of packages that belongs to specified local transaction. /// </summary> /// <param name="transactionId">The local transaction id.</param> /// <returns><c>true</c> if send is successful; otherwise, <c>false</c>.</returns> private void SendLocalTransaction(Guid transactionId) { IEnumerable <ICommunicationPackage> packages = from communicationPackage in this.XmlList where communicationPackage.XmlData.LocalTransactionId == transactionId orderby communicationPackage.OrderNumber ascending select communicationPackage; bool isLast = false; ICommunicationPackage lastPackage = packages.Last(); foreach (ICommunicationPackage communicationPackage in packages) { if (communicationPackage == lastPackage) { isLast = true; } else { isLast = false; } while (SendPackage(communicationPackage.Clone() as ICommunicationPackage, isLast) == false) { Wait(); } SetXmlSentWithRetry(communicationPackage.XmlData.Id); if (isLast == false) { Wait(); } } }
public override bool ExecutePackage(ICommunicationPackage communicationPackage) { SessionManager.VolatileElements.DeferredTransactionId = communicationPackage.XmlData.DeferredTransactionId; SessionManager.VolatileElements.LocalTransactionId = this.LocalTransactionId; try { if (this.IsHeadquarter == true) { if (base.ExecutePackage(communicationPackage) == false) { return(false); } } else { this.CurrentPackage = new DBXml(XDocument.Parse(communicationPackage.XmlData.Content)); } if (this.CurrentPackage.Table("documentAttrValue") == null) { throw new Exception("CommercialDocumentExScript: Brak atrybutu Attribute_TargetBranchId"); } string targetBranch = PackageExecutionHelper.GetDocumentAttrValue(this.CurrentPackage.Table("documentAttrValue").Xml, Makolab.Fractus.Kernel.Enums.DocumentFieldName.Attribute_TargetBranchId, "textValue"); if (targetBranch == null) { throw new Exception("CommercialDocumentExScript: Brak atrybutu Attribute_TargetBranchId"); } Guid targetBranchId = new Guid(targetBranch); if (PackageExecutionHelper.IsSameDatabase(Makolab.Fractus.Kernel.Mappers.ConfigurationMapper.Instance.DatabaseId, targetBranchId) == true) { using (Kernel.Coordinators.DocumentCoordinator coordinator = new Makolab.Fractus.Kernel.Coordinators.DocumentCoordinator(false, false)) { coordinator.CreateOrUpdateReservationFromOrder(this.CurrentPackage.Xml.Root); } } else if (this.IsHeadquarter == true && MustForwardPackage()) { ForwardPackage(communicationPackage, targetBranchId); } } catch (SqlException e) { if (e.Number == 50012) // Conflict detection { throw new ConflictException("Conflict detected while changing " + this.MainObjectTag + " id: " + this.CurrentPackage.Table(this.MainObjectTag).FirstRow().Element("id").Value); } else { this.Log.Error("CommercialDocumentExScript:ExecutePackage " + e.ToString()); return(false); } } return(true); }
/// <summary> /// Validates the specified communication package and throws exception when package is invalid. /// </summary> /// <param name="package">The communication package.</param> /// <exception cref="XmlSchemaValidationException">Xml is invalid.</exception> public void Validate(ICommunicationPackage package) { if (this.schemas.ContainsKey(package.XmlData.XmlType)) { System.Xml.Linq.XDocument doc = System.Xml.Linq.XDocument.Parse(package.XmlData.Content); doc.Validate(this.schemas[package.XmlData.XmlType], null); } }
/// <summary> /// Process data that was received by web service method. /// </summary> /// <param name="data">The data received via web service method call.</param> /// <returns>Response to web service client.</returns> public object DataReceived(object data) { SendDataParameters methodParams = (SendDataParameters)data; if (methodParams == null) { return(null); } SendDataResponse response = new SendDataResponse(); ICommunicationPackage communicationPackage = (methodParams.Xml == null) ? null : CreateCommunicationPackage(methodParams); DatabaseConnector.DatabaseConnectorManager dbm = GetDatabaseConnector(); dbm.StartModule(); try { using (IUnitOfWork uow = new UnitOfWork(dbm)) { uow.MapperFactory = IoC.Get <IMapperFactory>(); uow.StartTransaction(IsolationLevel.Serializable); CommunicationPackageRepository repo = new CommunicationPackageRepository(uow); if (communicationPackage != null) { repo.Add(communicationPackage); } if (methodParams.IsLastInTransaction) { repo.MarkTransactionAsCompleted(communicationPackage.XmlData.LocalTransactionId); } if (methodParams.Statistics != null) { repo.UpdateStatistics(methodParams.Statistics, methodParams.DepartmentIdentifier); } uow.SubmitChanges(); } } catch (System.Data.SqlClient.SqlException e) { response.Result = false; Log.Error(e.ToString(), false); return(response); } catch (CommunicationPackageExistsException e) //Xml already in database. { Log.Info(e.ToString(), false); } finally { dbm.StopModule(); } response.Result = true; return(response); }
/// <summary> /// Sends the communication packages. /// </summary> private void SendXmlPackages() { if (this.XmlList.Count > 0) { ICommunicationPackage communicationPackage = this.XmlList[0]; SendLocalTransaction(communicationPackage.XmlData.LocalTransactionId); this.XmlList.RemoveAll(p => p.XmlData.LocalTransactionId == communicationPackage.XmlData.LocalTransactionId); } }
/// <summary> /// Process communication package persisting it's data to database. /// </summary> /// <param name="communicationPackage">The communication package to execute.</param> /// <returns> /// <c>true</c> if execution succeeded; otherwise, <c>false</c> /// </returns> public override bool ExecutePackage(ICommunicationPackage communicationPackage) { SessionManager.VolatileElements.DeferredTransactionId = communicationPackage.XmlData.DeferredTransactionId; SessionManager.VolatileElements.LocalTransactionId = this.LocalTransactionId; this.CurrentPackage = new DBXml(XDocument.Parse(communicationPackage.XmlData.Content)); List <Guid> relationsId = new List <Guid>(); foreach (DBRow row in this.CurrentPackage.Table(this.MainObjectTag).Rows) { Guid relationId = new Guid(row.Element("id").Value); relationsId.Add(relationId); } DBXml dbSnapshot = GetCurrentSnapshot(relationsId); try { // TODO conflict detection & resolution //// Conflict detection //if (dbSnapshot != null && ValidateVersion(CurrentPackage, dbSnapshot) == false) //{ // throw new ConflictException("Conflict detected while changing " + this.MainObjectTag + " id: " + mainObjectId.ToString()); //} PackageExecutionHelper.RemoveDeletedRows(this.CurrentPackage, dbSnapshot, this.MainObjectTag, this.Log); if (this.CurrentPackage.Table(MainObjectTag).HasRows == false) { return(true); } //else do the rest DBXml changeset = GenerateChangeset(CurrentPackage, dbSnapshot); ExecuteChangeset(changeset); } catch (SqlException e) { if (e.Number == 50012) // Conflict detection { throw new ConflictException("Conflict detected while changing " + this.MainObjectTag); } else { this.Log.Error("SnapshotScript:ExecutePackage " + e.ToString()); return(false); } } return(true); }
/// <summary> /// Validates the specified communication package. /// </summary> /// <param name="package">The communication package.</param> /// <param name="validationExceptionMessage">The validation exception message.</param> /// <returns> /// <c>true</c> if communication package is valid; otherwise, <c>false</c> /// </returns> /// <remarks>When communication pakage is invalid method returns <c>false</c> and <c>validationExceptionMessage</c> parameter contains validation error message.</remarks> public bool Validate(ICommunicationPackage package, ref string validationExceptionMessage) { try { Validate(package); return(true); } catch (XmlSchemaValidationException e) { validationExceptionMessage = e.ToString(); return(false); } }
/// <summary> /// Forwards the communication package in headquarter branch. /// </summary> /// <param name="communicationPackage">The communication package.</param> /// <param name="repository">The communication package repository.</param> private void ForwardInHeadquarter(ICommunicationPackage communicationPackage, ICommunicationPackageRepository repository) { XDocument commPkg = XDocument.Parse(communicationPackage.XmlData.Content); var skipPackage = XDocument.Parse(communicationPackage.XmlData.Content).Root.Attribute("skipPackage"); if (skipPackage != null && skipPackage.Value.Equals("true", StringComparison.OrdinalIgnoreCase)) { return; } CommunicationPackageType pkgType = GetPackageType(communicationPackage); if (pkgType == CommunicationPackageType.Configuration || pkgType == CommunicationPackageType.ContractorSnapshot || pkgType == CommunicationPackageType.ContractorRelations || pkgType == CommunicationPackageType.ContractorGroupMembership || pkgType == CommunicationPackageType.ItemSnapshot || pkgType == CommunicationPackageType.ItemRelation || pkgType == CommunicationPackageType.ItemGroupMembership || pkgType == CommunicationPackageType.ItemUnitRelation || pkgType == CommunicationPackageType.WarehouseStock || pkgType == CommunicationPackageType.Payment || //pkgType == CommunicationPackageType.PaymentSettlementSnapshot || pkgType == CommunicationPackageType.FileDescriptor || pkgType == CommunicationPackageType.DictionaryPackage || pkgType == CommunicationPackageType.PriceRule || pkgType == CommunicationPackageType.PriceRuleList || pkgType == CommunicationPackageType.Custom) { IEnumerable <Guid> destinationDatabases = GetDestinations(communicationPackage, repository.Context.ConnectionManager); if (destinationDatabases != null) { repository.PutToOutgoingQueue(communicationPackage, destinationDatabases); } } else if (pkgType == CommunicationPackageType.WarehouseDocumentSnapshot) { if (commPkg.Root.Element("warehouseDocumentLine").Elements("entry").All(row => row.Element("isDistributed").Value.Equals("1"))) { ForwardShiftDocument(communicationPackage, repository, commPkg); } } else if (pkgType == CommunicationPackageType.WarehouseDocumentValuation) { // zapobiega zapetleniu paczek if (communicationPackage.DatabaseId != this.currentDatabaseId) { ForwardValuations(communicationPackage, commPkg, repository); } } }
private ICommunicationPackage CreateCommunicationPackage(SendDataParameters methodParams) { ICommunicationPackage communicationPackage = IoC.Get <ICommunicationPackageFactory>().CreatePackage(methodParams.Xml); communicationPackage.DatabaseId = methodParams.DepartmentIdentifier; communicationPackage.Decompress(); //log when package is invalid but save it anyway if (communicationPackage.CheckSyntax() == false) { Log.Error("Invalid xml received - syntax error. Xml Id=" + communicationPackage.XmlData.Id); } return(communicationPackage); }
/// <summary> /// Validates the specified communication package. /// </summary> /// <param name="package">The communication package.</param> /// <param name="validationExceptionMessage">The validation exception message.</param> /// <returns> /// <c>true</c> if communication package is valid; otherwise, <c>false</c> /// </returns> /// <remarks>When communication pakage is invalid method returns <c>false</c> and <c>validationExceptionMessage</c> parameter contains validation error message.</remarks> public bool Validate(ICommunicationPackage package, ref string validationExceptionMessage) { bool validationResult = false; foreach (var validator in this.validators) { validationResult = validator.Validate(package, ref validationExceptionMessage); if (validationResult == false) { return(false); } } return(true); }
/// <summary> /// Saves the specified xml to storage. /// </summary> /// <param name="xmlData">The xml to save.</param> /// <param name="databaseId">The database id.</param> /// <returns> /// <c>true</c> if is saving successful; otherwise, <c>false</c>. /// </returns> public bool ProcessXml(XmlTransferObject xmlData, Guid?databaseId) { bool isSaved = false; ICommunicationPackage xml = this.packageFactory.CreatePackage(xmlData); xml.DatabaseId = databaseId; xml.Decompress(); if (xml.CheckSyntax()) { int retryCount = 0; using (IUnitOfWork uow = Manager.CreateUnitOfWork()) { uow.MapperFactory = this.mapperFactory; CommunicationPackageRepository repo = new CommunicationPackageRepository(uow); while (isSaved == false && retryCount < 10) { try { repo.Add(xml); isSaved = true; } catch (SqlException) { ++retryCount; Wait(); } catch (CommunicationPackageExistsException e) // Xml with the same id exists in db { this.Log.Info(e.ToString(), false); isSaved = true; } } if (!isSaved) { Log.Error("EXCEPTION: CRITICAL ERROR ALERT! What to do with unset (Saves the specified xml to storage) ProcessXml(XmlTransferObject xmlData,Guid? databaseId) PackageReceiver.cs"); } } } else { Log.Error("Invalid xml received, syntax error. Xml id=" + xmlData.Id + " content=" + xmlData.Content); ////it shouldnt be received in the first place = validation on the WebService site return(false); } return(isSaved); }
/// <summary> /// Puts the communication package in outgoing queue. /// </summary> /// <param name="xml">The XML package to save.</param> /// <param name="targetBranches">The target branches.</param> public void SaveOutgoingPackage(ICommunicationPackage xml, IEnumerable <Guid> targetBranches) { if (xml == null) { throw new ArgumentNullException("xml"); } if (targetBranches == null || targetBranches.Count() == 0) { return; } DBTable outgoingXmlQueue = new DBXml().AddTable("outgoingXmlQueue"); foreach (var branchId in targetBranches) { DBRow row = outgoingXmlQueue.AddRow(); row.AddElement("id", Guid.NewGuid().ToUpperString()); row.AddElement("localTransactionId", xml.XmlData.LocalTransactionId.ToUpperString()); row.AddElement("deferredTransactionId", xml.XmlData.DeferredTransactionId.ToUpperString()); row.AddElement("databaseId", branchId.ToUpperString()); row.AddElement("type", xml.XmlData.XmlType); row.AddElement("xml", XElement.Parse(xml.XmlData.Content)); } SqlCommand cmd = this.helper.CreateCommand(StoredProcedure.communication_p_insertOutgoingPackage.ToProcedureName(), new SqlParameter("@xmlVar", SqlDbType.Xml), this.helper.CreateSqlXml(outgoingXmlQueue.Document.Xml)); using (this.Database.SynchronizeConnection()) { try { cmd.ExecuteNonQuery(); } catch (SqlException e) { if (e.Number == 2627) { throw new CommunicationPackageExistsException("Communication package with the same id already exists in the database.", xml.XmlData.Id.ToString(), e); } else { throw; } } } }
private void ForwardPackage(ICommunicationPackage communicationPackage, Guid targetBranchId) { XmlTransferObject forwardedPkgData = new XmlTransferObject { DeferredTransactionId = communicationPackage.XmlData.DeferredTransactionId, Id = Guid.NewGuid(), LocalTransactionId = Guid.NewGuid(), XmlType = "CommercialDocumentSnapshotEx", Content = this.CurrentPackage.Xml.ToString(System.Xml.Linq.SaveOptions.DisableFormatting) }; ICommunicationPackage pkg = new CommunicationPackage(forwardedPkgData); pkg.DatabaseId = Makolab.Fractus.Kernel.Mappers.DictionaryMapper.Instance.GetBranch(targetBranchId).DatabaseId; CommunicationPackageRepository pkgRepo = new CommunicationPackageRepository(this.UnitOfWork); pkgRepo.PutToOutgoingQueue(pkg); }
public override bool ExecutePackage(ICommunicationPackage communicationPackage) { SessionManager.VolatileElements.DeferredTransactionId = communicationPackage.XmlData.DeferredTransactionId; SessionManager.VolatileElements.LocalTransactionId = this.LocalTransactionId; try { XDocument commPkg = XDocument.Parse(communicationPackage.XmlData.Content); this.repository.ExecuteOperations(new DBXml(commPkg)); return(true); } catch (SqlException e) { this.Log.Error("CustomScript:ExecutePackage " + e.ToString()); return(false); } }
/// <summary> /// Executes the communication package. /// </summary> /// <param name="communicationPackage">The communication package to execute.</param> /// <returns> /// <c>true</c> if execution succeeded; otherwise, <c>false</c> /// </returns> public override bool ExecutePackage(ICommunicationPackage communicationPackage) { try { SessionManager.VolatileElements.DeferredTransactionId = communicationPackage.XmlData.DeferredTransactionId; SessionManager.VolatileElements.LocalTransactionId = this.LocalTransactionId; XDocument commXml = XDocument.Parse(communicationPackage.XmlData.Content); foreach (var row in commXml.Root.Element("configuration").Elements("entry")) { var action = row.Attribute("action"); if (action != null && action.Value == DBRowState.Delete.ToStateName()) { this.mapper.DeleteConfiguration(new Guid(row.Element("id").Value)); } } var updated = XDocument.Parse("<root><configuration/></root>"); var inserted = XDocument.Parse("<root><configuration/></root>"); updated.Root.Element("configuration").Add(from row in commXml.Root.Element("configuration").Elements("entry") where row.Element("version") != null && row.Element("_version") != null select row); inserted.Root.Element("configuration").Add(from row in commXml.Root.Element("configuration").Elements("entry") where row.Element("version") == null && row.Element("_version") != null select row); if (updated.Root.Element("configuration").Elements("entry").Count() > 0) { this.mapper.UpdateConfiguration(updated); } if (inserted.Root.Element("configuration").Elements("entry").Count() > 0) { this.mapper.InsertConfiguration(inserted); } return(true); } catch (SqlException e) { this.Log.Error("ConfigurationMapper:ExecutePackage " + e.ToString()); return(false); } }
/// <summary> /// Gets the type of the specified communication package. /// </summary> /// <param name="communicationPackage">The communication package.</param> /// <returns>Communication package type</returns> private CommunicationPackageType GetPackageType(ICommunicationPackage communicationPackage) { CommunicationPackageType pkgType; try { pkgType = (CommunicationPackageType)Enum.Parse(typeof(CommunicationPackageType), communicationPackage.XmlData.XmlType); } catch (ArgumentException) { this.Log.Info(String.Format("Unknown package type - {0} in package {1}", communicationPackage.XmlData.XmlType, communicationPackage.XmlData.Id)); pkgType = CommunicationPackageType.Unknown; } return(pkgType); }
/// <summary> /// Process communication package persisting it's data to database. /// </summary> /// <param name="communicationPackage">The communication package to execute.</param> /// <returns> /// <c>true</c> if execution succeeded; otherwise, <c>false</c> /// </returns> public override bool ExecutePackage(ICommunicationPackage communicationPackage) { if (base.ExecutePackage(communicationPackage) == false) { return(false); } CommunicationPackage payment = PackageExecutionHelper.ExtractPaymentPackage(this.CurrentPackage, communicationPackage); if (payment != null) { payment.XmlData.LocalTransactionId = this.LocalTransactionId; var pkgRepo = new CommunicationPackageRepository(this.UnitOfWork); var forwarder = Makolab.Fractus.Commons.DependencyInjection.IoC.Get <IPackageForwarder>(); forwarder.Log = this.Log; forwarder.ForwardPackage(payment, pkgRepo); } return(true); }
/// <summary> /// Saves the package. /// </summary> /// <param name="xml">The XML package to save.</param> public virtual void SavePackage(ICommunicationPackage xml) { if (xml == null) { throw new ArgumentNullException("xml"); } DBRow row = new DBXml().AddTable("incomingXmlQueue").AddRow(); row.AddElement("id", xml.XmlData.Id.ToUpperString()); row.AddElement("localTransactionId", xml.XmlData.LocalTransactionId.ToUpperString()); row.AddElement("deferredTransactionId", xml.XmlData.DeferredTransactionId.ToUpperString()); row.AddElement("databaseId", xml.DatabaseId); row.AddElement("type", xml.XmlData.XmlType); row.AddElement("xml", XElement.Parse(xml.XmlData.Content)); SqlCommand cmd = this.helper.CreateCommand(StoredProcedure.communication_p_insertIncomingPackage.ToProcedureName(), new SqlParameter("@xmlVar", SqlDbType.Xml), this.helper.CreateSqlXml(row.Table.Document.Xml)); using (this.Database.SynchronizeConnection()) { try { cmd.ExecuteNonQuery(); } catch (SqlException e) { if (e.Number == 2627) { //xml with the same id is already in database so we assume that it's the same and skip this one usually //but its other method decision throw new CommunicationPackageExistsException("Communication package with the same id already exists in the database.", xml.XmlData.Id.ToString(), e); } else { throw; } } } }
/// <summary> /// Task main method. /// </summary> /// <remarks> /// Run method steps: /// 1. Retrives unprocessed packages. /// 2. Creates objects that process packages. /// 3. Sets execution flag for processed packages. /// 4. Pauses before repeating process. /// </remarks> protected override void Run() { this.executionManager.Initialize(Manager.Database); this.scriptFactory.IsHeadquarter = this.Manager.IsHeadquarter; this.packageForwarder.Log = this.Manager.Log; this.executionManager.Log = this.Manager.Log; while (this.IsEnabled) { Wait(); try { this.XmlList.Clear(); GetNewXmlPackages(); if (this.XmlList.Count > 0) { lock (Makolab.Fractus.Communication.Transmitter.TransmitterSemaphore.locker) { ICommunicationPackage communicationPackage = this.XmlList.Single(pkg => pkg.OrderNumber == this.XmlList.Min(cpkg => cpkg.OrderNumber)); if (ExecuteLocalTransaction(communicationPackage.XmlData.LocalTransactionId)) { this.XmlList.RemoveAll(p => p.XmlData.LocalTransactionId == communicationPackage.XmlData.LocalTransactionId); } else { throw new InvalidOperationException("this.XmlList.RemoveAll(p => p.XmlData.LocalTransactionId == communicationPackage.XmlData.LocalTransactionId);"); } } } } catch (Exception e) { this.Manager.Log.Error(String.Format(System.Globalization.CultureInfo.InvariantCulture, "Uncaught exception in PackageExecutor: {0}", e.ToString())); } } this.executionManager.Clean(Manager.Database); }
/// <summary> /// Gets the destinations departments for specified communication package. /// </summary> /// <param name="communicationPackage">The communication package.</param> /// <param name="dbMan">The database connection manager.</param> /// <returns>Collection of destination department ids.</returns> internal IEnumerable <Guid> GetDestinations(ICommunicationPackage communicationPackage, IDatabaseConnectionManager dbMan) { if (this.destinations == null) { Makolab.Fractus.Communication.DBLayer.CommunicationPackageMapper mapper = new Makolab.Fractus.Communication.DBLayer.CommunicationPackageMapper(dbMan); destinations = mapper.GetDestinations(); } CommunicationPackageType type = GetPackageType(communicationPackage); if (this.destinations.ContainsKey(type) == false) { return(null); } return((from branch in this.destinations[type] where branch.DatabaseId != communicationPackage.DatabaseId.Value && branch.DatabaseId != currentDatabaseId.Value select branch.DatabaseId).Distinct()); }
/// <summary> /// Forwards the specified package to other departments. /// </summary> /// <param name="communicationPackage">The communication package.</param> /// <param name="repository">The communication package repository.</param> public void ForwardPackage(ICommunicationPackage communicationPackage, ICommunicationPackageRepository repository) { //TODO //mechanism that deley insertion of forwarded packages if executing in deffered mode //not a major problem because everything is in the same transaction, but constansts rollback will mess with order column if (this.isHQ == null) { SetHeadquater(repository.Context); } if (this.currentDatabaseId == null) { SetDatabaseId(repository.Context); } if (this.isHQ == true) { ForwardInHeadquarter(communicationPackage, repository); } //else ForwardInBranch }
/// <summary> /// Process communication package persisting it's data to database. /// </summary> /// <param name="communicationPackage">The communication package to execute.</param> /// <returns> /// <c>true</c> if execution succeeded; otherwise, <c>false</c> /// </returns> public override bool ExecutePackage(ICommunicationPackage communicationPackage) { SessionManager.VolatileElements.DeferredTransactionId = communicationPackage.XmlData.DeferredTransactionId; SessionManager.VolatileElements.LocalTransactionId = this.LocalTransactionId; this.CurrentPackage = new DBXml(XDocument.Parse(communicationPackage.XmlData.Content)); Guid mainObjectId = new Guid(this.CurrentPackage.Table(MainObjectTag).FirstRow().Element("id").Value); DBXml dbSnapshot = GetCurrentSnapshot(mainObjectId); try { // TODO conflict detection & resolution //if (dbSnapshot != null && ValidateVersion(CurrentPackage, dbSnapshot) == false) //{ // throw new ConflictException("Conflict detected while changing " + this.MainObjectTag + " id: " + mainObjectId.ToString()); //} DBXml changeset = GenerateChangeset(CurrentPackage, dbSnapshot); if (changeset != null && changeset.Tables.Count() > 0) { ExecuteChangeset(changeset); } } catch (SqlException e) { if (e.Number == 50012) // Conflict detection { throw new ConflictException("Conflict detected while changing " + this.MainObjectTag + " id: " + mainObjectId.ToString()); } else { this.Log.Error("SnapshotScript:ExecutePackage " + e.ToString()); return(false); } } return(true); }
/// <summary> /// Executes the communication package. /// </summary> /// <param name="communicationPackage">The communication package to execute.</param> /// <returns> /// <c>true</c> if execution succeeded; otherwise, <c>false</c> /// </returns> public override bool ExecutePackage(ICommunicationPackage communicationPackage) { SessionManager.VolatileElements.DeferredTransactionId = communicationPackage.XmlData.DeferredTransactionId; SessionManager.VolatileElements.LocalTransactionId = this.LocalTransactionId; try { XDocument commPkg = XDocument.Parse(communicationPackage.XmlData.Content); var warehouseDocumentIdElement = commPkg.Root.Element("id"); if (warehouseDocumentIdElement == null || warehouseDocumentIdElement.Value.Length == 0) { throw new InvalidDataException("Invalid xml data."); } Guid warehouseDocumentId = new Guid(warehouseDocumentIdElement.Value); this.repository.UnrelateWarehouseDocumentForIncome(warehouseDocumentId); return(true); } catch (SqlException e) { this.Log.Error("UnrelateWarehouseDocumentForOutcome:ExecutePackage " + e.ToString()); return(false); } }
/// <summary> /// Determines whether the execution of specified communication package is required or package must be skipped. /// </summary> /// <param name="communicationPackage">The communication package.</param> /// <returns> /// <c>true</c> if execution is required; otherwise, <c>false</c>. /// </returns> public bool IsExecutionRequired(ICommunicationPackage communicationPackage) { if (this.exceptionalPackages.Contains(communicationPackage.XmlData.XmlType)) { var skipPackage = XDocument.Parse(communicationPackage.XmlData.Content).Root.Attribute("skipPackage"); if (skipPackage != null && skipPackage.Value.Equals("true", StringComparison.OrdinalIgnoreCase)) { return(false); } else { return(true); } } else if (this.isHeadquarter == false || (this.isHeadquarter && communicationPackage.DatabaseId.Value != this.currentDatabaseId)) { return(true); } else { return(false); } }
/// <summary> /// Executes the communication package. /// </summary> /// <param name="communicationPackage">The communication package to execute.</param> /// <returns> /// <c>true</c> if execution succeeded; otherwise, <c>false</c> /// </returns> public override bool ExecutePackage(ICommunicationPackage communicationPackage) { SessionManager.VolatileElements.DeferredTransactionId = communicationPackage.XmlData.DeferredTransactionId; SessionManager.VolatileElements.LocalTransactionId = this.LocalTransactionId; try { XDocument commPkg = XDocument.Parse(communicationPackage.XmlData.Content); var commercialDocumentIdElement = commPkg.Root.Element("id"); if (commercialDocumentIdElement == null || commercialDocumentIdElement.Value.Length == 0) { throw new InvalidDataException("Invalid xml data."); } Guid commercialDocumentId = new Guid(commercialDocumentIdElement.Value); var pkgRepo = new CommunicationPackageRepository(this.UnitOfWork); this.repository.UnrelateCommercialDocument(commercialDocumentId, this.LocalTransactionId, communicationPackage.XmlData.DeferredTransactionId, pkgRepo.GetDatabaseId()); return(true); } catch (SqlException e) { this.Log.Error("UnrelateCommercialDocument:ExecutePackage " + e.ToString()); return(false); } }
private static void ForwardShiftDocument(ICommunicationPackage communicationPackage, ICommunicationPackageRepository repository, XDocument commPkg) { using (var wrapper = repository.Context.ConnectionManager.SynchronizeConnection()) { SqlConnectionManager.Instance.SetConnection(wrapper.Connection, (SqlTransaction)repository.Context.Transaction); } DocumentType docType = DictionaryMapper.Instance.GetDocumentType(new Guid( commPkg.Root.Element("warehouseDocumentHeader") .Element("entry").Element("documentTypeId").Value)); if (docType.WarehouseDocumentOptions.WarehouseDirection != Makolab.Fractus.Kernel.Enums.WarehouseDirection.OutcomeShift || docType.DocumentCategory == DocumentCategory.IncomeWarehouseCorrection || docType.DocumentCategory == DocumentCategory.OutcomeWarehouseCorrection) { return; } string oppositeWarehouseFieldId = DictionaryMapper.Instance.GetDocumentField(Makolab.Fractus.Kernel.Enums.DocumentFieldName.ShiftDocumentAttribute_OppositeWarehouseId).Id.Value.ToString().ToUpperInvariant(); string oppositeWarehouseId = commPkg.Root.Element("documentAttrValue").Elements() .Where(row => row.Element("documentFieldId").Value.Equals(oppositeWarehouseFieldId)) .Select(row => row.Element("textValue").Value) .SingleOrDefault(); if (oppositeWarehouseId == null) { throw new InvalidDataException("Missing opposite warehouse id in document attributes"); } Warehouse oppositeWarehouse = DictionaryMapper.Instance.GetWarehouse(new Guid(oppositeWarehouseId)); Warehouse warehouse = DictionaryMapper.Instance.GetWarehouse(new Guid(commPkg.Root.Element("warehouseDocumentHeader").Element("entry").Element("warehouseId").Value)); //skip local shift documents if (warehouse.BranchId != oppositeWarehouse.BranchId) { communicationPackage.DatabaseId = DictionaryMapper.Instance.GetBranch(oppositeWarehouse.BranchId).DatabaseId; repository.PutToOutgoingQueue(communicationPackage); } }
/// <summary> /// Respond to request for data received by web service method call. /// (TODO wtf translate the above comment to english please :) ) /// </summary> /// <param name="data">The data received via web service method call.</param> /// <returns>Response to web service client.</returns> public object DataRequested(object data) { GetDataParameters methodParams = (GetDataParameters)data; if (methodParams == null) { return(null); } DatabaseConnector.DatabaseConnectorManager dbm = GetDatabaseConnector(); dbm.StartModule(); //ICommunicationPackageMapper mapper = NullMapperFactory.Instance.CreateMapper<ICommunicationPackageMapper>(dbm); List <ICommunicationPackage> packagesQueue = null; try { using (IUnitOfWork uow = new UnitOfWork(dbm)) { uow.MapperFactory = IoC.Get <IMapperFactory>(); CommunicationPackageRepository repo = new CommunicationPackageRepository(uow); if (methodParams.LastReceivedXmlId != null) { repo.MarkAsSend(methodParams.LastReceivedXmlId.Value); } packagesQueue = repo.FindUndeliveredPackages(1, methodParams.LastReceivedXmlId, methodParams.DatabaseId); if (packagesQueue.Count == 0) { return(null); } ICommunicationPackage pkg = packagesQueue.Single(cPkg => cPkg.OrderNumber == packagesQueue.Min(communicationPackage => communicationPackage.OrderNumber)); //IEnumerable<ICommunicationPackage> tmp = packagesQueue.Where(cPkg => cPkg.BranchId == methodParams.DatabaseId); //ICommunicationPackage pkg = tmp.Single(cPkg => cPkg.OrderNumber == tmp.Min(communicationPackage => communicationPackage.OrderNumber)); //from pkg2 in packagesQueue where pkg2.OrderNumber == packagesQueue.Min(communicationPackage => communicationPackage.OrderNumber) select pkg2; //packagesQueue[packagesQueue.Min(communicationPackage => communicationPackage.OrderNumber) - 1]; if (pkg.CheckSyntax() == false) { Log.Error("Invalid xml in outgoing queue.- syntax error. Xml Id=" + pkg.XmlData.Id); return(null); } if (isValidationEnabled) { if (validator == null) { object context = IoC.Get <IContextProvider>().CreateContext(IoC.Container(), "IDatabaseConnectionManager", uow.ConnectionManager); //throws XmlSchemaValidationException this.validator = IoC.Get <IPackageValidator>(context); } this.validator.ConnectionManager = uow.ConnectionManager; this.validator.Validate(pkg); } pkg.Compress(); GetDataResponse response = new GetDataResponse(); response.XmlData = pkg.XmlData; response.DatabaseId = pkg.DatabaseId; response.AdditionalData = GetUndeliveredPackagesQuantity(response.AdditionalData, repo, methodParams); return(response); } } finally { dbm.StopModule(); } }