Compare commits
	
		
			5 Commits
		
	
	
		
			playwright
			...
			open245
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | ab4d73dba6 | ||
|   | 92755f040c | ||
|   | 551f95363f | ||
|   | 7f5ce2e712 | ||
|   | e0c5cb099d | 
							
								
								
									
										32
									
								
								platform/persistence/multi/bundle.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								platform/persistence/multi/bundle.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,32 @@ | ||||
| { | ||||
|     "extensions": { | ||||
|         "components": [ | ||||
|             { | ||||
|                 "type": "decorator", | ||||
|                 "provides": "persistenceService", | ||||
|                 "implementation": "MultiPersistenceDecorator.js", | ||||
|                 "depends": [ | ||||
|                     "persistenceService", | ||||
|                     "$q", | ||||
|                     "MULTI_PERSISTENCE_SPACE_MAPPINGS", | ||||
|                     "MULTI_PERSISTENCE_DEFAULT_SPACE", | ||||
|                     "PERSISTENCE_SPACE" | ||||
|                 ] | ||||
|             } | ||||
|         ], | ||||
|         "constants": [ | ||||
|             { | ||||
|                 "key": "MULTI_PERSISTENCE_SPACE_MAPPINGS", | ||||
|                 "value": {}, | ||||
|                 "priority": "fallback", | ||||
|                 "comment": "Maps identifiers to persistence spaces (statically.)" | ||||
|             }, | ||||
|             { | ||||
|                 "key": "MULTI_PERSISTENCE_DEFAULT_SPACE", | ||||
|                 "value": "mct", | ||||
|                 "priority": "fallback", | ||||
|                 "comment": "Should be overridden with a reasonable default." | ||||
|             } | ||||
|         ] | ||||
|     } | ||||
| } | ||||
							
								
								
									
										73
									
								
								platform/persistence/multi/src/AsyncMutex.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										73
									
								
								platform/persistence/multi/src/AsyncMutex.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,73 @@ | ||||
| /***************************************************************************** | ||||
|  * Open MCT Web, Copyright (c) 2014-2015, United States Government | ||||
|  * as represented by the Administrator of the National Aeronautics and Space | ||||
|  * Administration. All rights reserved. | ||||
|  * | ||||
|  * Open MCT Web is licensed under the Apache License, Version 2.0 (the | ||||
|  * "License"); you may not use this file except in compliance with the License. | ||||
|  * You may obtain a copy of the License at | ||||
|  * http://www.apache.org/licenses/LICENSE-2.0. | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, software | ||||
|  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | ||||
|  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | ||||
|  * License for the specific language governing permissions and limitations | ||||
|  * under the License. | ||||
|  * | ||||
|  * Open MCT Web includes source code licensed under additional open source | ||||
|  * licenses. See the Open Source Licenses file (LICENSES.md) included with | ||||
|  * this source code distribution or the Licensing information page available | ||||
|  * at runtime from the About dialog for additional information. | ||||
|  *****************************************************************************/ | ||||
| /*global define,Promise*/ | ||||
|  | ||||
| define( | ||||
|     [], | ||||
|     function () { | ||||
|         'use strict'; | ||||
|  | ||||
|         function AsyncMutex($q) { | ||||
|             this.queue = []; | ||||
|             this.$q = $q; | ||||
|         } | ||||
|  | ||||
|         AsyncMutex.prototype.acquire = function (callback) { | ||||
|             var deferred = this.$q.defer(), | ||||
|                 queue = this.queue; | ||||
|  | ||||
|             function advance() { | ||||
|                 if (queue.length > 0) { | ||||
|                     queue.shift()(); | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             function release(result) { | ||||
|                 deferred.resolve(result); | ||||
|                 advance(); | ||||
|             } | ||||
|  | ||||
|             function next() { | ||||
|                 try { | ||||
|                     callback(release); | ||||
|                 } catch (e) { | ||||
|                     deferred.reject(e); | ||||
|                     advance(); | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             queue.push(next); | ||||
|             if (queue.length === 1) { | ||||
|                 advance(); | ||||
|             } | ||||
|  | ||||
|             return deferred.promise; | ||||
|         }; | ||||
|  | ||||
|         AsyncMutex.prototype.use = function (callback) { | ||||
|             return this.acquire(function (release) { | ||||
|                 release(callback); | ||||
|             }); | ||||
|         }; | ||||
|  | ||||
|     } | ||||
| ); | ||||
							
								
								
									
										125
									
								
								platform/persistence/multi/src/MultiPersistenceDecorator.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										125
									
								
								platform/persistence/multi/src/MultiPersistenceDecorator.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,125 @@ | ||||
| /***************************************************************************** | ||||
|  * Open MCT Web, Copyright (c) 2014-2015, United States Government | ||||
|  * as represented by the Administrator of the National Aeronautics and Space | ||||
|  * Administration. All rights reserved. | ||||
|  * | ||||
|  * Open MCT Web is licensed under the Apache License, Version 2.0 (the | ||||
|  * "License"); you may not use this file except in compliance with the License. | ||||
|  * You may obtain a copy of the License at | ||||
|  * http://www.apache.org/licenses/LICENSE-2.0. | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, software | ||||
|  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | ||||
|  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | ||||
|  * License for the specific language governing permissions and limitations | ||||
|  * under the License. | ||||
|  * | ||||
|  * Open MCT Web includes source code licensed under additional open source | ||||
|  * licenses. See the Open Source Licenses file (LICENSES.md) included with | ||||
|  * this source code distribution or the Licensing information page available | ||||
|  * at runtime from the About dialog for additional information. | ||||
|  *****************************************************************************/ | ||||
| /*global define*/ | ||||
|  | ||||
| /** | ||||
|  * This bundle implements a persistence service which uses ElasticSearch to | ||||
|  * store documents. | ||||
|  * @namespace platform/persistence/elastic | ||||
|  */ | ||||
| define( | ||||
|     ['./PersistenceTable'], | ||||
|     function (PersistenceTable) { | ||||
|         'use strict'; | ||||
|  | ||||
|         function MultiPersistenceDecorator( | ||||
|             persistenceService, | ||||
|             $q, | ||||
|             spaceMappings, | ||||
|             defaultSpace, | ||||
|             spaceToRemap | ||||
|         ) { | ||||
|             this.table = new PersistenceTable( | ||||
|                 persistenceService, | ||||
|                 $q, | ||||
|                 spaceMappings, | ||||
|                 defaultSpace | ||||
|             ); | ||||
|             this.spaceToRemap = spaceToRemap; | ||||
|             this.persistenceService = persistenceService; | ||||
|             this.$q = $q; | ||||
|         } | ||||
|  | ||||
|         // Public API | ||||
|         MultiPersistenceDecorator.prototype.listSpaces = function () { | ||||
|             var spaceToRemap = this.spaceToRemap, | ||||
|                 mappedSpaces = this.table.getSpaces(); | ||||
|  | ||||
|             return this.persistenceService.listSpaces.then(function (spaces) { | ||||
|                 // Hide the existence of alternate spaces; make them | ||||
|                 // appear as the one global space for storing domain objects. | ||||
|                 return spaces.filter(function (space) { | ||||
|                     return mappedSpaces.indexOf(space) === -1; | ||||
|                 }).concat([spaceToRemap]); | ||||
|             }); | ||||
|         }; | ||||
|  | ||||
|         MultiPersistenceDecorator.prototype.listObjects = function (space) { | ||||
|             var persistenceService = this.persistenceService; | ||||
|             if (space === this.spaceToRemap) { | ||||
|                 return this.$q.all(this.mappedSpaces.map(function (s) { | ||||
|                     return persistenceService.listObjects(s); | ||||
|                 })).then(function (lists) { | ||||
|                     return lists.reduce(function (a, b) { | ||||
|                         return a.concat(b); | ||||
|                     }, []); | ||||
|                 }); | ||||
|             } | ||||
|             return persistenceService.listObjects(space); | ||||
|         }; | ||||
|  | ||||
|         MultiPersistenceDecorator.prototype.createObject = function (space, key, value) { | ||||
|             var persistenceService = this.persistenceService, | ||||
|                 table = this.table; | ||||
|             if (space === this.spaceToRemap) { | ||||
|                 return table.getSpace(value.location).then(function (s) { | ||||
|                     return table.setSpace(key, s).then(function () { | ||||
|                         return persistenceService.createObject(s, key, value); | ||||
|                     }); | ||||
|                 }); | ||||
|             } | ||||
|             return persistenceService.createObject(space, key, value); | ||||
|         }; | ||||
|  | ||||
|         MultiPersistenceDecorator.prototype.readObject = function (space, key) { | ||||
|             var persistenceService = this.persistenceService; | ||||
|             if (space === this.spaceToRemap) { | ||||
|                 return this.table.getSpace(key).then(function (s) { | ||||
|                     return persistenceService.readObject(s, key); | ||||
|                 }); | ||||
|             } | ||||
|             return persistenceService.readObject(space, key); | ||||
|         }; | ||||
|  | ||||
|         MultiPersistenceDecorator.prototype.updateObject = function (space, key, value) { | ||||
|             var persistenceService = this.persistenceService, | ||||
|                 table = this.table, | ||||
|                 self = this; | ||||
|             if (space === this.spaceToRemap) { | ||||
|                 return this.table.getSpace(key).then(function (currentSpace) { | ||||
|                     return this.table.getSpace(value.location).then(function (newSpace) { | ||||
|                         // TODO: Also move children when space change happens? | ||||
|                         return (newSpace === currentSpace) ? | ||||
|                                 persistenceService.updateObject(newSpace, key, value) : | ||||
|                                 self.createObject(space, key, value); | ||||
|                     }); | ||||
|                 }); | ||||
|             } | ||||
|             return persistenceService.createObject(space, key, value); | ||||
|         }; | ||||
|  | ||||
|         MultiPersistenceDecorator.prototype.deleteObject = function (space, key, value) { | ||||
|         }; | ||||
|  | ||||
|         return MultiPersistenceDecorator; | ||||
|     } | ||||
| ); | ||||
							
								
								
									
										77
									
								
								platform/persistence/multi/src/PersistenceTable.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								platform/persistence/multi/src/PersistenceTable.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,77 @@ | ||||
| /***************************************************************************** | ||||
|  * Open MCT Web, Copyright (c) 2014-2015, United States Government | ||||
|  * as represented by the Administrator of the National Aeronautics and Space | ||||
|  * Administration. All rights reserved. | ||||
|  * | ||||
|  * Open MCT Web is licensed under the Apache License, Version 2.0 (the | ||||
|  * "License"); you may not use this file except in compliance with the License. | ||||
|  * You may obtain a copy of the License at | ||||
|  * http://www.apache.org/licenses/LICENSE-2.0. | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, software | ||||
|  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | ||||
|  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | ||||
|  * License for the specific language governing permissions and limitations | ||||
|  * under the License. | ||||
|  * | ||||
|  * Open MCT Web includes source code licensed under additional open source | ||||
|  * licenses. See the Open Source Licenses file (LICENSES.md) included with | ||||
|  * this source code distribution or the Licensing information page available | ||||
|  * at runtime from the About dialog for additional information. | ||||
|  *****************************************************************************/ | ||||
| /*global define,Promise*/ | ||||
|  | ||||
| define( | ||||
|     ['./AsyncMutex', './PersistenceTableInitializer'], | ||||
|     function (AsyncMutex, PersistenceTableInitializer) { | ||||
|         'use strict'; | ||||
|  | ||||
|         function PersistenceTable( | ||||
|             persistenceService, | ||||
|             $q, | ||||
|             spaceMappings, | ||||
|             defaultSpace | ||||
|         ) { | ||||
|             var spaces = Object.keys(spaceMappings).map(function (id) { | ||||
|                     return spaceMappings[id]; | ||||
|                 }).sort().filter(function (item, i, arr) { | ||||
|                     return i === 0 || arr[i - 1] !== item; | ||||
|                 }), | ||||
|                 initializer = | ||||
|                     new PersistenceTableInitializer($q, persistenceService), | ||||
|                 self = this; | ||||
|  | ||||
|  | ||||
|             this.mutex = new AsyncMutex($q); | ||||
|             this.$q = $q; | ||||
|             this.staticSpaceMappings = spaceMappings; | ||||
|             this.defaultSpace = defaultSpace; | ||||
|             this.spaces = spaces; | ||||
|  | ||||
|             this.mutex.acquire(function (release) { | ||||
|                 initializer.initialTable(spaces).then(function (table) { | ||||
|                     self.observedSpaceMappings = table; | ||||
|                 }).then(release); | ||||
|             }); | ||||
|         } | ||||
|  | ||||
|         PersistenceTable.prototype.setSpace = function (id, space) { | ||||
|             var mappings = this.observedSpaceMappings; | ||||
|             return this.mutex.use(function () { | ||||
|                 this.observedSpaceMappings[id] = space; | ||||
|             }); | ||||
|         }; | ||||
|  | ||||
|         PersistenceTable.prototype.getSpace = function (id) { | ||||
|             var self = this; | ||||
|             return this.mutex.use(function () { | ||||
|                 return self.staticSpaceMappings[id] || | ||||
|                     self.observedSpaceMappings[id]; | ||||
|             }); | ||||
|         }; | ||||
|  | ||||
|         PersistenceTable.prototype.getSpaces = function () { | ||||
|             return this.spaces; | ||||
|         }; | ||||
|     } | ||||
| ); | ||||
| @@ -0,0 +1,77 @@ | ||||
| /*global define*/ | ||||
| define( | ||||
|     [], | ||||
|     function () { | ||||
|         'use strict'; | ||||
|  | ||||
|         function PersistenceTableInitializer($q, persistenceService) { | ||||
|             this.$q = $q; | ||||
|             this.persistenceService = persistenceService; | ||||
|         } | ||||
|  | ||||
|         PersistenceTableInitializer.prototype.initialTable = function (spaces) { | ||||
|             var persistenceService = this.persistenceService, | ||||
|                 $q = this.$q, | ||||
|                 unreconciledSpaceMappings = {}, | ||||
|                 reconciledSpaceMappings = {}; | ||||
|  | ||||
|             function initializeSpace(space) { | ||||
|                 return persistenceService.listObjects().then(function (ids) { | ||||
|                     ids.forEach(function (id) { | ||||
|                         unreconciledSpaceMappings[id] = | ||||
|                             unreconciledSpaceMappings[id] || []; | ||||
|                         unreconciledSpaceMappings[id].push(space); | ||||
|                     }); | ||||
|                 }); | ||||
|             } | ||||
|  | ||||
|             function choose(models) { | ||||
|                 var index = 0, | ||||
|                     greatest = Number.NEGATIVE_INFINITY; | ||||
|  | ||||
|                 models.forEach(function (model, i) { | ||||
|                     if (model.persisted !== undefined && | ||||
|                             model.persisted > greatest) { | ||||
|                         greatest = model.persisted; | ||||
|                         index = i; | ||||
|                     } | ||||
|                 }); | ||||
|  | ||||
|                 return index; | ||||
|             } | ||||
|  | ||||
|             function reconcileConflict(id) { | ||||
|                 var candidateSpaces = unreconciledSpaceMappings[id]; | ||||
|                 return $q.all(candidateSpaces.map(function (space) { | ||||
|                     return persistenceService.readObject(space, id); | ||||
|                 })).then(choose).then(function (index) { | ||||
|                     reconciledSpaceMappings[id] = candidateSpaces[index]; | ||||
|                 }); | ||||
|             } | ||||
|  | ||||
|             function reconcileConflicts() { | ||||
|                 var toReconcile = []; | ||||
|                 Object.keys(unreconciledSpaceMappings).forEach(function (id) { | ||||
|                     if (unreconciledSpaceMappings[id].length > 1) { | ||||
|                         toReconcile.push(id); | ||||
|                     } else { | ||||
|                         reconciledSpaceMappings[id] = | ||||
|                             unreconciledSpaceMappings[id][0]; | ||||
|                     } | ||||
|                 }); | ||||
|                 return $q.all(toReconcile.map(reconcileConflict)); | ||||
|             } | ||||
|  | ||||
|             function giveResult() { | ||||
|                 return reconciledSpaceMappings; | ||||
|             } | ||||
|  | ||||
|             return $q.all(spaces.map(initializeSpace)) | ||||
|                 .then(reconcileConflicts) | ||||
|                 .then(giveResult); | ||||
|         }; | ||||
|  | ||||
|  | ||||
|  | ||||
|     } | ||||
| ); | ||||
		Reference in New Issue
	
	Block a user