-
-
Notifications
You must be signed in to change notification settings - Fork 169
GridFs Migration
You can share/migrate files between Meteor applications via DDP on a server/database level without the need for complex setups. This is due to the circumstance, that GridFS makes use of a normal Mongo.Collection to store metadata and chunks.
This topic can be of relevance for Services or Microservices, that don't share a database but have to share their data.
Consider two Meteor applications C (Consumer) and P (Provider) where C wants to synchronize all files from P. The sync will happen without clients (browsers/devices) being involved and the files and documents won't be mutated.
First create three Methods in P that each share one of the three crucial Parts of a FilesCollection
:
- Sharing the
FilesCollection
's documents - Sharing the
fs.files
* metadata for the files' respective subversions - Sharing the
fs.chunks
* (the actual data) of all stored files and their subversions
This assumes the default configuration of your GridFS which is by default using the db.fs.files
and db.fs.chunks
collections.
For custom configuration you may consult the JS Mongo Native Driver documentation on GridFSBucket.
import { Meteor } from 'meteor/meteor'
import { Mongo } from 'meteor/mongo'
import { FilesCollection } from 'meteor/ostrio:files'
const ImageFiles = new FilesCollection({ ... })
const FsFiles = new Mongo.Collection('fs.files')
const FsChunks = new Mongo.Collection('fs.chunks')
function getFilesDocuments () {
return ImageFiles.collection.find().fetch()
}
function getFilesMetadata () {
return FsFiles.find().fetch()
}
function getFilesChunks () {
return FsChunks.find().fetch()
}
Meteor.methods({getFilesDocuments, getFilesMetadata, getFilesChunks})
import { Meteor } from 'meteor/meteor'
import { Mongo } from 'meteor/mongo'
import { DDP } from 'meteor/ddp-client'
import { Tracker } from 'meteor/tracker'
import { FilesCollection } from 'meteor/ostrio:files'
const ImageFiles = new FilesCollection({ ... })
const FsFiles = new Mongo.Collection('fs.files')
const FsChunks = new Mongo.Collection('fs.chunks')
let remoteConnection // use to connect to P via DDP
/**
* Inserts a doc into a collection or updates the doc, if it already exists
*/
function insertUpdate(collection, doc) {
if (!collection.findOne(doc._id)) {
console.log(`[${collection._name}]: insert ${collection.insert(doc)}`)
} else {
const docId = doc._id
delete doc._id
const updated = collection.update(docId, { $set: doc })
console.log(`[${collection._name}]: update ${docId} ${updated}`)
}
}
/**
* Call the methods on the remote application and insert/update the received documents
*/
function synchronize (trackerComputation) {
// skip if not yet connected
if (!remoteConnection.status().connected) return
remoteConnection.call('getFilesDocuments', (err, filesDocuments) => {
// handle err
filesDocuments.forEach(filesDoc => insertUpdate(ImageFiles.collection, filesDoc))
})
remoteConnection.call('getFilesMetadata', (err, filesMetdadata) => {
// handle err
filesMetdadata.forEach(metadataDoc => insertUpdate(FsFiles, metadataDoc))
})
remoteConnection.call('getFilesChunks', (err, filesChunks) => {
// handle err
filesChunks.forEach(chunkDoc => insertUpdate(FsChunks, chunkDoc))
})
// stop the tracker because we don't need to watch the connection anymore
trackerComputation.stop()
}
// ... code continues in the next step
In your Consumer application C you can now connect to the remote app on the server-side.
Meteor.startup(() => {
const url = 'p.domain.tld' // get url of P, for example via process.env or Meteor.settings
remoteConnection = DDP.connect(url)
// use Tracker to run the sync when the remoteConnection is "connected"
const synchronizeTracker = Meteor.bindEnvironment(synchronize)
Tracker.autorun(synchronizeTracker)
})
You may require authentication for the remote connection, which can be added using ongoworks:ddp-login
.
A good pattern is to create a user that is only permitted to run the sync methods in P and login with that user from C. The credentials for login can be passed using process.env
or Meteor.settings
.
From this point you can configure your methods to sync only a subset of documents or manipulate them before/after sync or remove them after sync.
Meteor-Files | Support | Try ostr.io |
---|---|---|
If you found this package useful, — star it at GitHub and support our open source contributions with a monthly pledge, or submit a one-time donation via PayPal | Monitoring, Analytics, WebSec, Web-CRON and Pre-rendering for a website |