public void ShouldExportObjectsFromQueue() { const int currentRecord = 4560; _jobContext.SetCurrentRecord(currentRecord); var syncObject1 = new SyncObject(ObjectType) { QueueId = 4561 }; var syncObject2 = new SyncObject(ObjectType) { QueueId = 4562 }; var syncObject3 = new SyncObject(ObjectType) { QueueId = 4563 }; var pulledObjects1 = new List<SyncObject> { syncObject1, syncObject2 }; var pulledObjects2 = new List<SyncObject> { syncObject3 }; _source.Setup(source => source.GetBatchOfObjects(ObjectType, QueueName, BatchSize, currentRecord)).Returns(pulledObjects1); _source.Setup(source => source.GetBatchOfObjects(ObjectType, QueueName, BatchSize, syncObject2.QueueId)).Returns(pulledObjects2); _source.Setup(source => source.GetBatchOfObjects(ObjectType, QueueName, BatchSize, syncObject3.QueueId)).Returns(new List<SyncObject>()); var exception = new SaveToSalsaException("test failure"); _destination.Setup(d => d.Save(syncObject1)).Throws(exception); _destination.Setup(d => d.Save(syncObject2)).Returns(true); _destination.Setup(d => d.Save(syncObject3)).Returns(false); _exporter.Start(_jobContext); _errorHandler.Verify(h => h.HandleSyncObjectFailure(syncObject1, _exporter, exception)); _source.Verify(s => s.UpdateStatus(QueueName, 4561, QueueRepository.QueueStatusError, null)); _source.Verify(s => s.UpdateStatus(QueueName, 4562, QueueRepository.QueueStatusExported, It.IsAny<DateTime>())); _source.Verify(s => s.UpdateStatus(QueueName, 4563, QueueRepository.QueueStatusSkipped, It.IsAny<DateTime>())); _source.Verify(s => s.Dequeue(QueueName, 4561), Times.Never()); _source.Verify(s => s.Dequeue(QueueName, 4562)); _source.Verify(s => s.Dequeue(QueueName, 4563)); Assert.AreEqual(1, _jobContext.SuccessCount); Assert.AreEqual(1, _jobContext.IdenticalObjectCount); }
public void ShouldSynchronize() { var minimumModificationDate = new DateTime(2012, 5, 20); const int currentRecord = 4560; _jobContext.MinimumModificationDate = minimumModificationDate; _jobContext.SetCurrentRecord(currentRecord); var syncObject1 = new SyncObject(ObjectType) { SalsaKey = 4561 }; var syncObject2 = new SyncObject(ObjectType) { SalsaKey = 4562 }; var syncObject3 = new SyncObject(ObjectType) { SalsaKey = 4563 }; IEnumerable<SyncObject> pulledObjects1 = new List<SyncObject> { syncObject1, syncObject2 }; IEnumerable<SyncObject> pulledObjects2 = new List<SyncObject> { syncObject3 }; _sourceMock.Setup(source => source.GetBatchOfObjects(ObjectType, BatchSize, currentRecord, minimumModificationDate)).Returns(pulledObjects1); _sourceMock.Setup(source => source.GetBatchOfObjects(ObjectType, BatchSize, syncObject2.SalsaKey, minimumModificationDate)).Returns(pulledObjects2); var error = new Exception("test error"); _destinationMock.Setup(d => d.Enqueue(QueueName, syncObject1)).Throws(error); _importer.Start(_jobContext); _errorHandler.Verify(h => h.HandleSyncObjectFailure(syncObject1, _importer, error)); _destinationMock.Verify(queueRepository => queueRepository.Enqueue(QueueName, syncObject2)); _destinationMock.Verify(queueRepository => queueRepository.Enqueue(QueueName, syncObject3)); Assert.AreEqual(2, _jobContext.SuccessCount); }
private static bool IsObjectDifferent(SyncObject aftObject, SyncObject salsaObject, FieldMapping mapping) { var aftValue = aftObject[mapping.AftField]; var salsValue = salsaObject[mapping.AftField]; if (aftValue == null && salsValue == null) return false; if (aftValue == null) return true; return !aftValue.Equals(salsValue); }
public void ShouldGetPrimaryKeyMappingWhenPrimaryRuleIsPresented() { var aftObject = new SyncObject(ObjectType){SalsaKey = 1234}; aftObject["Email"] = "*****@*****.**"; var nameValues = _mapper.ToSalsa(aftObject, null); Assert.AreEqual("*****@*****.**", nameValues["email"]); Assert.IsNull(nameValues["key"]); }
public void ShouldCreateNameValuePairsFromSyncObjectWithDateTime() { var syncObject = new SyncObject(ObjectType); syncObject["CustomDate1"] = new DateTime(2012, 08, 29, 12, 34, 56); var nameValues = _mapper.ToSalsa(syncObject, null); Assert.AreEqual(2, nameValues.Keys.Count); Assert.AreEqual("2012-08-29 12:34:56", nameValues["custom_date1"]); }
public void ShouldBeIdenticalIfAftWinsFieldsHaveSameValue() { var aftObject = new SyncObject(ObjectType); aftObject["CustomDate1"] = new DateTime(2012, 8, 23); var salsaObject = new SyncObject(ObjectType); salsaObject["CustomDate1"] = new DateTime(2012, 8, 23); Assert.IsTrue(_comparator.AreIdentical(aftObject, salsaObject, _mappings)); }
public void ShouldBeIdenticalIfGroupIdIs0() { var chapterKey = 0; var supporterKey = 5678; var aftObject = new SyncObject(ObjectType) { SalsaKey = supporterKey }; aftObject["ChapterKey"] = chapterKey; var salsaObject = new SyncObject(ObjectType); Assert.IsTrue(_comparator.AreIdentical(aftObject, salsaObject, _mappings)); }
public void ShouldGetPrimaryKeyMappingAsTheSalsaKeyMappingWhenPrimaryRuleIsNotPresented() { _mappings.First(m => m.AftField == "Email").MappingRule = MappingRules.aftWins; var aftObject = new SyncObject(ObjectType){SalsaKey = 1234}; aftObject["Email"] = "*****@*****.**"; var nameValues = _mapper.ToSalsa(aftObject, null); Assert.AreEqual("*****@*****.**", nameValues["email"]); Assert.AreEqual("1234", nameValues["key"]); }
private void Enqueue(SyncObject obj, IJobContext jobContext) { try { _destination.Enqueue(_queueName, obj); jobContext.CountSuccess(); } catch(Exception ex) { _errorHandler.HandleSyncObjectFailure(obj, this, ex); } }
public void ShouldGetBatchOfObjects() { var syncObject = new SyncObject(ObjectType) { QueueId = 123 }; var xElement = XElement.Parse("<item/>"); var xElements = new List<XElement> {xElement}; var dateTime = new DateTime(2012, 7, 20); _salsaClient.Setup(s => s.GetObjects(ObjectType, 10, 200, dateTime, _expectedSalsaFields)).Returns(xElements); _mapperMock.Setup(m => m.ToAft(xElement)).Returns(syncObject); _mapperMock.Setup(m => m.Mappings).Returns(_fieldMappings); Assert.AreEqual(syncObject, _repository.GetBatchOfObjects(ObjectType, 10, 200, dateTime).First()); }
public void ShouldBeIdenticalIfMembershipExists() { var chapterKey = 1234; var supporterKey = 5678; var aftObject = new SyncObject(ObjectType); aftObject["ChapterKey"] = chapterKey; var salsaObject = new SyncObject(ObjectType) { SalsaKey = supporterKey }; _salsaClient.Setup(s => s.DoesMembershipExist("chapter", ObjectType, chapterKey.ToString(), supporterKey.ToString())) .Returns(true); Assert.IsTrue(_comparator.AreIdentical(aftObject, salsaObject, _mappings)); }
public void SetUp() { Config.Environment = Config.Test; _mapperFactoryMock = new Mock<IMapperFactory>(); var mapping1 = new FieldMapping {AftField = "First_Name", SalsaField = "First_Name", DataType = DataType.String}; var mapping2 = new FieldMapping {AftField = "Last_Name", SalsaField = "Last_Name", DataType = DataType.String}; var mapping3 = new FieldMapping { AftField = "ProcessedDate", DataType = DataType.DateTime }; var mapping4 = new FieldMapping {AftField = "Email", DataType = DataType.String}; var mapping5 = new FieldMapping {AftField = "PE_Pub", DataType = DataType.Boolean}; _mapper = new Mapper(ObjectType, new List<FieldMapping>{mapping1, mapping2, mapping3, mapping4, mapping5}); _repository = new QueueRepository(_mapperFactoryMock.Object); _syncObject = new SyncObject(ObjectType); TestUtils.ClearAllQueues(); }
public void Enqueue(string tableName, SyncObject syncObject) { var fields = syncObject.FieldNames.Where(field => syncObject[field] != null); using (var connection = new SqlConnection(Config.DbConnectionString)) { connection.Open(); var columnNames = String.Join(",", fields); var parameterPlaceholders = String.Join(",", fields.Select(f => String.Format("@{0}", f))); var insertStatement = String.Format("INSERT {0} ({1}) VALUES ({2});", tableName, columnNames, parameterPlaceholders); var command = new SqlCommand(insertStatement, connection); var parameters = fields .Select(f => new SqlParameter(f, syncObject[f])).ToList(); command.Parameters.AddRange(parameters.ToArray()); command.ExecuteNonQuery(); } }
public void SetUp() { Config.Environment = Config.Test; TestUtils.ClearAllSessions(); TestUtils.RemoveAllSalsa("supporter_chapter"); TestUtils.RemoveAllSalsa("supporter"); TestUtils.RemoveAllSalsa("chapter"); TestUtils.ClearAllQueues(); TestUtils.EnsureSupporterCustomColumn("cdb_match_date", "datetime"); _supporterOne = MakeSupporter("One"); _supporterTwo = MakeSupporter("Two"); _chapterOne = MakeChapter("One"); _chapterTwo = MakeChapter("Two"); TestUtils.RecreateFieldMappingForTest(); }
public bool AreIdentical(SyncObject aftObject, SyncObject salsaObject, List<FieldMapping> mappings) { if (salsaObject == null) return false; foreach (var mapping in mappings) { if (mapping.MappingRule.EqualsIgnoreCase(MappingRules.aftWins) && IsObjectDifferent(aftObject, salsaObject, mapping)) return false; if (!mapping.MappingRule.EqualsIgnoreCase(MappingRules.onlyIfBlank) || !IsSalsaFieldBlank(salsaObject, mapping)) continue; if (IsObjectDifferent(aftObject, salsaObject, mapping)) return false; } var membershipMapping = mappings.FirstOrDefault(m => m.MappingRule.EqualsIgnoreCase(MappingRules.writeOnlyNewMembership)); if (membershipMapping == null || aftObject[membershipMapping.AftField] == null || aftObject[membershipMapping.AftField].Equals(0)) return true; var groupType = membershipMapping.SalsaField.Split('_').First(); //membership field is like "chapter_key" var doesMembershipExist = _salsaClient.DoesMembershipExist(groupType, aftObject.ObjectType, aftObject[membershipMapping.AftField].ToString(), salsaObject.SalsaKey.ToString()); return doesMembershipExist; }
public bool Save(SyncObject aftObject) { try { var mapper = _mapperFactory.GetMapper(aftObject.ObjectType); var salsaFields = mapper.Mappings.Select(mapping => mapping.SalsaField).ToList(); var primaryKeyMapping = mapper.PrimaryKeyMapping; Logger.Trace("got primaryKeyMapping" + primaryKeyMapping.AftField + ":" + primaryKeyMapping.SalsaField); var salsaXml = _salsa.GetObjectBy(aftObject.ObjectType, primaryKeyMapping.SalsaField, aftObject[primaryKeyMapping.AftField].ToString(), salsaFields); Logger.Trace("got salsaXml"); var salsaObject = mapper.ToAft(salsaXml); if (_objectComparator.AreIdentical(aftObject, salsaObject, mapper.Mappings)) return false; Logger.Trace("Saving to salsa"); aftObject.SalsaKey = int.Parse(_salsa.Save(aftObject.ObjectType, mapper.ToSalsa(aftObject, salsaObject))); return true; } catch(Exception ex) { Logger.Error("Got an error when saving object to salsa", ex); throw new SaveToSalsaException("Got error when saving object to Salsa.", ex); } }
private void ExportSyncObject(SyncObject syncObject, IJobContext jobContext) { try { if (_destination.Save(syncObject)) { _source.UpdateStatus(_queueName, syncObject.QueueId, QueueRepository.QueueStatusExported, DateTime.Now); jobContext.CountSuccess(); } else { _source.UpdateStatus(_queueName, syncObject.QueueId, QueueRepository.QueueStatusSkipped, DateTime.Now); jobContext.CountIdenticalObject(); } _source.Dequeue(_queueName, syncObject.QueueId); } catch (SaveToSalsaException ex) { _errorHandler.HandleSyncObjectFailure(syncObject, this, ex); _source.UpdateStatus(_queueName, syncObject.QueueId, QueueRepository.QueueStatusError); } }
public List<SyncObject> GetBatchOfObjects(string objectType, string tableName, int batchSize, int startKey) { var mapper = _mapperFactory.GetMapper(objectType); var sql = String.Format("SELECT top {0} * FROM {1} WHERE (Status != '{2}' OR Status IS NULL) AND Id > {3} ORDER BY Id", batchSize, tableName, QueueStatusError, startKey); var returnValue = new List<SyncObject>(); using (var dataAdaptor = new SqlDataAdapter(sql, Config.DbConnectionString)) { var dataSet = new DataSet(); dataAdaptor.Fill(dataSet); var table = dataSet.Tables[0]; foreach (DataRow row in table.Rows) { var syncObject = new SyncObject(objectType); foreach (DataColumn column in table.Columns) { SetValueToSyncObject(row, column, syncObject, mapper); } returnValue.Add(syncObject); } } Logger.Trace("Got batch from queque:" + tableName + " started from: " + startKey); return returnValue; }
public void ShouldAlwaysSaveObjectForNewObject() { var key = 1234; SyncObject salsaObj = null; var salsaXml = XElement.Parse("<item></item>"); var primaryFieldMapping = new FieldMapping{AftField = "Email", SalsaField = "email"}; var mappings = new List<FieldMapping>{new FieldMapping{SalsaField = "Email"}, new FieldMapping{SalsaField = "Address"}}; var aftObj = new SyncObject(ObjectType) {SalsaKey = 0}; aftObj["Email"] = "*****@*****.**"; var nameValues = new NameValueCollection(); _mapperMock.SetupGet(m => m.PrimaryKeyMapping).Returns(primaryFieldMapping); _mapperMock.SetupGet(m => m.Mappings).Returns(mappings); _salsaClient.Setup(s => s.GetObjectBy(ObjectType, primaryFieldMapping.SalsaField, aftObj[primaryFieldMapping.AftField].ToString(), It.IsAny<IEnumerable<string>>())).Returns(salsaXml); _mapperMock.Setup(m => m.ToAft(salsaXml)).Returns(salsaObj); _mapperMock.Setup(m => m.ToSalsa(aftObj, salsaObj)).Returns(nameValues); _salsaClient.Setup(s => s.Save(ObjectType, nameValues)).Returns(key.ToString); var saved = _repository.Save(aftObj); Assert.IsTrue(saved); Assert.AreEqual(key, aftObj.SalsaKey); }
private static bool IsSalsaFieldBlank(SyncObject salsaObject, FieldMapping fieldMapping) { if (fieldMapping.DataType.EqualsIgnoreCase(DataType.Boolean)) return false; //blank cannot be applied to bool in salsa; return salsaObject[fieldMapping.AftField] == null; }
public void ShouldBeIdenticalIfOnlyIfBlankFieldIsBlankFromSalsaButAftHasTheSameValue() { var aftObject = new SyncObject(ObjectType); aftObject["Address"] = null; var salsaObject = new SyncObject(ObjectType); salsaObject["Address"] = null; Assert.IsTrue(_comparator.AreIdentical(aftObject, salsaObject, _mappings)); }
public void ShouldGetObject() { var key = 1234; var supporter = new SyncObject(ObjectType); var xElement = XElement.Parse("<item><key>1234</key></item>"); _salsaClient.Setup(s => s.GetObject(ObjectType, key.ToString())).Returns(xElement); _mapperMock.Setup(m => m.ToAft(xElement)).Returns(supporter); Assert.AreEqual(supporter, _repository.Get(ObjectType, key)); }
public void ShouldSkipObjectWhenGettingOneObjectFails() { var syncObject = new SyncObject(ObjectType) { QueueId = 123 }; var xElement = XElement.Parse("<item/>"); var xElements = new List<XElement> { xElement }; var dateTime = new DateTime(2012, 7, 20); var originalBatchSize = 1; var originalStartKey = 200; var nextKey = 202; _salsaClient.Setup(s => s.GetNextKey(ObjectType, originalStartKey, dateTime)).Returns(nextKey); var salsaClientException = new SalsaClientException("bad data"); _salsaClient.Setup(s => s.GetObjects(ObjectType, originalBatchSize, originalStartKey, dateTime, _expectedSalsaFields)).Throws(salsaClientException); _salsaClient.Setup(s => s.GetObjects(ObjectType, originalBatchSize, nextKey, dateTime, _expectedSalsaFields)).Returns(xElements); _mapperMock.Setup(m => m.ToAft(xElement)).Returns(syncObject); _mapperMock.Setup(m => m.Mappings).Returns(_fieldMappings); Assert.AreEqual(new List<SyncObject> { syncObject }, _repository.GetBatchOfObjects(ObjectType, originalBatchSize, originalStartKey, dateTime)); _errorHandlerMock.Verify(handler => handler.HandleSalsaClientException(ObjectType, nextKey, _repository, salsaClientException)); }
public void ShouldNotBeIdenticalWhenSalsaObjectIsNull() { var aftObject = new SyncObject(ObjectType); Assert.IsFalse(_comparator.AreIdentical(aftObject, null, _mappings)); }
public void ShouldNotBeIdenticalIfOnlyIfBlankFieldIsBlankFromSalsaButNotBlankFromAft() { var aftObject = new SyncObject(ObjectType); aftObject["Address"] = "Girk"; var salsaObject = new SyncObject(ObjectType); salsaObject["Address"] = null; Assert.IsFalse(_comparator.AreIdentical(aftObject, salsaObject, _mappings)); }
public void ShouldBeIdenticalIgnoringFieldsWithSalsaWinsReadOnlyWriteOnlyAndPrimaryKeyRules() { var aftObject = new SyncObject(ObjectType); aftObject["Email"] = "*****@*****.**"; aftObject["NickName"] = "Doo"; aftObject["SalsaLastModified"] = new DateTime(2012, 8, 23); aftObject["GroupKey"] = 20; var salsaObject = new SyncObject(ObjectType); salsaObject["Email"] = "*****@*****.**"; salsaObject["NickName"] = "Boo"; salsaObject["SalsaLastModified"] = new DateTime(2011, 9, 17); salsaObject["GroupKey"] = 98; Assert.IsTrue(_comparator.AreIdentical(aftObject, salsaObject, _mappings)); }
public void ShouldBeIdenticalIfOnlyIfBlankFieldIsNotBlankFromSalsa() { var aftObject = new SyncObject(ObjectType); aftObject["Address"] = "Girk"; var salsaObject = new SyncObject(ObjectType); salsaObject["Address"] = "Duke"; Assert.IsTrue(_comparator.AreIdentical(aftObject, salsaObject, _mappings)); }
public void ShouldCheckIfMembershipExist() { var chapter = new SyncObject("chapter"); chapter["Name"] = "Chapter0"; TestUtils.InsertToSalsa(chapter); NameValueCollection supporter = GenerateSupporter(); supporter["chapter_KEY"] = chapter.SalsaKey.ToString(); var supporterKey = client.Save("supporter", supporter); Assert.IsTrue(client.DoesMembershipExist("chapter", "supporter",chapter.SalsaKey.ToString(), supporterKey)); Assert.IsFalse(client.DoesMembershipExist("chapter", "supporter", chapter.SalsaKey.ToString(), "somethingNotExist")); }
public void HandleSyncObjectFailure(SyncObject obj, object destination, Exception ex) { Logger.Error(String.Format("Failed to sync object: {0}", obj), ex); var syncEventArgs = new SyncEventArgs { SyncObject = obj, Destination = destination, EventType = SyncEventType.Error, Error = ex }; HandleFailure(syncEventArgs); }
public void ShouldSkipBadDataInBatchFromSalsa() { var syncObject = new SyncObject(ObjectType) { QueueId = 123 }; var xElement = XElement.Parse("<item/>"); var xElements = new List<XElement> { xElement, xElement }; var dateTime = new DateTime(2012, 7, 20); _salsaClient.Setup(s => s.GetObjects(ObjectType, 10, 200, dateTime, _expectedSalsaFields)).Returns(xElements); _mapperMock.SetupSequence(m => m.ToAft(xElement)) .Returns(syncObject) .Throws(new FormatException("test exception")); _mapperMock.Setup(m => m.Mappings).Returns(_fieldMappings); IEnumerable<SyncObject> batchOfObjects = _repository.GetBatchOfObjects(ObjectType, 10, 200, dateTime).ToList(); Assert.AreEqual(1, batchOfObjects.Count()); Assert.AreEqual(syncObject, batchOfObjects.First()); }