test4.ts 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. /* ----------------------- TEST4 {Mongo to Mongo} ----------------------- */
  2. /* Same with test 3 but this one it will be working with CDMS or any other potential data.
  3. Highly advisable to refer to test3c for the overall explanation of the logic flow in these
  4. test cases. Test4 is an adjusted version of test3 to cater for the need to deal with
  5. different types of data aside from messageLogs. */
  6. import * as mongoose from 'mongoose'
  7. import { Observable, map, Subject, takeUntil, take, of, timer, from } from "rxjs";
  8. import { ErrorTrigger, MessageSynchronisationServiceSetting } from "../type/datatype";
  9. import { StreamingService } from "./test-streamOBS";
  10. import { MessageAuditorService } from "../services/message-auditor.service";
  11. import { LoggingService } from '../dependencies/log/interface/export';
  12. import { BaseMessage } from '../dependencies/msgutil/interface/export';
  13. import { LogSetting, MessageLog } from '../dependencies/log/type/datatype';
  14. import * as fs from "fs"
  15. /* Convert all the non message data in the database into messageLog type. This is to ensure it's compatibility
  16. to be used by the interface from logging and audit message features. */
  17. const Schema = mongoose.Schema;
  18. // Create the fingerprint schema. This is the type of the data to be transformed into messageLog type
  19. const fingerPrintSchema = new Schema({
  20. uuid: { type: String, required: true, lowercase: true, unique: true },
  21. fileName: { type: String, required: true, lowercase: true },
  22. fileType: { type: String, required: true, lowercase: true },
  23. entityName: { type: String, required: true, lowercase: true },
  24. fileData: { type: Object, required: true },
  25. });
  26. // Use existing schema.
  27. const messageSchema = require('../dependencies/log/type/schemas/message.schema')
  28. // This function is used for convert existing generic data in the designated database to be prepared for
  29. // AuditMessage service.
  30. function convertDataInMongo(url: string) {
  31. // Create a subject to stream data received from query at mongo, instantiate convert service and also the database location to read the datas
  32. let data: Subject<any> = new Subject()
  33. let convertService = new LoggingService()
  34. let dbConnection = mongoose.createConnection(url)
  35. let dataModel = dbConnection.model('genericdata', fingerPrintSchema)
  36. let messages = dbConnection.model('message', messageSchema)
  37. // Once the data is queried, it will be streamed into the data Subject declared earlier
  38. dataModel.find().then((res) => {
  39. // console.log(res)
  40. res.forEach((element) => {
  41. data.next(element)
  42. })
  43. })
  44. // Assign a `handler` so to speak to handle the element receivd in the data Subject
  45. // This is where the transformation happens. The logic is written on the logging service side.
  46. // Once that is done, the transformed data will be saved again bacn in the mongo database in a different databse/collection
  47. data.subscribe((element) => {
  48. let res = convertService.convertCDMStoMessageLog(element, settings.incomingSource.tags)
  49. console.log(`Converting fingerprint .... ${res.appData.msgId}`)
  50. messages.create(res)
  51. })
  52. }
  53. // These declaration are for the secondary to log the converted missing data back in it's own collection at their corresponding servers
  54. const dbConnection = mongoose.createConnection("mongodb+srv://testDB:h1nt1OyXw6QeUnzS@cluster0.29sklte.mongodb.net/secondary")
  55. const dataModel = dbConnection.model('genericdata', fingerPrintSchema)
  56. // TO be used by the secondary Subject to convert the message log it receives to complete the synchronization process.
  57. function convertMessageLogToCDMS(args: MessageLog){
  58. let converted = secondary_log.convertMessageLogtoCDMS(args)
  59. dataModel.create(converted)
  60. }
  61. /* For basic explanation, pleas refer to test3c. Here we are just instantiating audit and logging service for both
  62. the primary and the secondary soures. And then the instantiation of the corresponding subjects.
  63. The idea is that the subject will receive the missing info provided by the auditor and then log the
  64. missing data in the designated database location.
  65. */
  66. const primary_sync = new MessageAuditorService()
  67. const primary_Log = new LoggingService()
  68. const primary: Subject<MessageLog> = new Subject()
  69. primary.subscribe((element) => {
  70. console.log(`Primary Received ${element.appData.msgId}`)
  71. })
  72. const secondary_log = new LoggingService()
  73. const secondary: Subject<MessageLog> = new Subject()
  74. secondary.subscribe((element: MessageLog) => {
  75. console.log(`Secondary Received ${element.appData.msgId}`)
  76. convertMessageLogToCDMS(element)
  77. })
  78. /* For basic explanation, please refer to test3c. Declaration of the source and target location. */
  79. let primary_storage: LogSetting = {
  80. cacheMessageLimit: 0,
  81. storage: "MongoDB",
  82. setting: {
  83. appName: 'Default from client',
  84. appLocName: 'To be generated in client',
  85. logLocName: 'To be generated in client',
  86. },
  87. customSetting: {
  88. server: "192.168.100.59:27017",
  89. database: "primary"
  90. }
  91. }
  92. let secondary_storage: LogSetting = {
  93. cacheMessageLimit: 0,
  94. storage: "MongoDB",
  95. setting: {
  96. appName: 'Default from client',
  97. appLocName: 'To be generated in client',
  98. logLocName: 'To be generated in client',
  99. },
  100. customSetting: {
  101. srv: true,
  102. user: "testDB",
  103. password: "h1nt1OyXw6QeUnzS",
  104. server: "cluster0.29sklte.mongodb.net",
  105. database: "secondary",
  106. }
  107. }
  108. // Combine source and target storage to form MessageSynchronisationServiceSetting. This is required in messageAudit initialization
  109. let settings: MessageSynchronisationServiceSetting = {
  110. incomingSource: {
  111. //all of the settings to be combined here
  112. ...primary_storage,
  113. tags: ['Fingerprint']
  114. }, //LogSetting & {tags:string[] },
  115. target: {
  116. ...secondary_storage,
  117. tags: ['Fingerprint']
  118. } //LogSetting & {tags:string[] }
  119. }
  120. /* -------- SYNCHRONIZATION --------- */
  121. // Primary will call the syncrhonization service
  122. primary_sync.init(settings)
  123. /* This is where the synchronization logic is called. The errorSubject will act as a trigger
  124. mechanism to execute the synchronization. */
  125. let errorSubject: Subject<ErrorTrigger> = new Subject()
  126. // Subscribe to errorSubject notification
  127. let sync = primary_sync.subscribe(errorSubject)
  128. sync.subscribe({
  129. next: (msgToBeSynchronized: MessageLog) => {
  130. console.log(`passing missing message: ${msgToBeSynchronized.appData.msgId} into target/secondary subject.`)
  131. // the missing data returned will be pushed (next(message)) into the target payload.
  132. secondary.next(msgToBeSynchronized)
  133. }
  134. })
  135. // Set time oout for 5 seconds to allow the initial logging stage to complete it's logging
  136. // implementation first before proceedint to trigger the sync
  137. setTimeout(() => {
  138. // This wil act as the trigger error.Although the definition of this error is
  139. // still subject for enhancements in the near future.
  140. let sampleError: ErrorTrigger = {
  141. status: 1,
  142. message: "NO. I dont want to work"
  143. }
  144. errorSubject.next(sampleError)
  145. }, 3000)
  146. /* THis is testing for generating error message to be fed into the error subject
  147. to act as additional trigger to exectute the synchronization when there's no internet
  148. connection. */
  149. const dns = require('dns');
  150. // Function to check internet connectivity. Basically just look up the site of example.com
  151. // using the built in libray of DNS.
  152. function checkInternetConnectivity() {
  153. dns.lookup('example.com', (err) => {
  154. if (err && err.code === 'ENOTFOUND') {
  155. let errorMsg: ErrorTrigger = {
  156. status: 0,
  157. message: `No internet connection`
  158. }
  159. errorSubject.next(errorMsg)
  160. } else {
  161. // Emit a message indicating internet connectivity
  162. // console.log('Internet connection is available');
  163. }
  164. });
  165. }
  166. // Interval time (in milliseconds) for checking connectivity
  167. const intervalTime = 1000; // Check every 1 second
  168. // Start checking connectivity at intervals
  169. const interval = setInterval(checkInternetConnectivity, intervalTime);
  170. // Stop checking connectivity after a certain duration (e.g., 1 minute)
  171. const duration = 60000; // 1 minute
  172. setTimeout(function () {
  173. clearInterval(interval);
  174. console.log('Internet connectivity monitoring stopped');
  175. }, duration);
  176. function countdown() {
  177. let seconds = 0;
  178. const countUpInterval = setInterval(() => {
  179. console.log(`Elapsed seconds: ${seconds}`);
  180. seconds++;
  181. }, 1000); // Update every second (1000 milliseconds)
  182. }
  183. countdown()
  184. convertDataInMongo('mongodb://192.168.100.59:27017/primary')
  185. convertDataInMongo('mongodb+srv://testDB:h1nt1OyXw6QeUnzS@cluster0.29sklte.mongodb.net/secondary')
  186. // // Manually log the missing data given by audit
  187. secondary_log.init(settings.target).then(() => {
  188. secondary_log.subscribe(secondary)
  189. })