Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Delete is not removing files from s3 bucket. #4

Closed
rgruesbeck opened this issue Oct 23, 2014 · 9 comments
Closed

Delete is not removing files from s3 bucket. #4

rgruesbeck opened this issue Oct 23, 2014 · 9 comments

Comments

@rgruesbeck
Copy link

Hi, my image files are not being deleted along with the model.
my model and crate config look like this.

var path = require('path');
var mongoose = require('mongoose');
var timestamps = require('mongoose-times');
var URLSlugs = require('mongoose-url-slugs');
var crate = require('mongoose-crate');
var S3 = require('mongoose-crate-s3');
var ImageMagick = require('mongoose-crate-imagemagick');
var Schema = mongoose.Schema;

var aws = require('../config/env').config().aws;

var crateConfig = {
  storage: new S3({
    key: aws.accessKeyId,
    secret: aws.secretAccessKey,
    bucket: aws.bucket,
    acl: 'public-read',
    region: aws.region,
    path: function(image) {
      return '/images/' + path.basename(image.path);
    }
  }),
  fields: {
    image: {
      processor: new ImageMagick({
        tmpDir: '/tmp/ImageMagick',
        formats: ['JPEG', 'GIF', 'PNG'],
        transforms: {
          original: {
            format: '.jpg'
          },
          medium: {
            resize: '640x480',
            format: '.jpg'
          },
          small: {
            resize: '320x240',
            format: '.jpg'
          }
        }
      })
    }
  }
};

var postsSchema = new Schema({
  title: { type:String, required:true },
  body: { type:String, required:true },
  author: { type:String, required:true },
  published: { type:Boolean, required:true, default:false }
});

postsSchema.plugin(timestamps);
postsSchema.plugin(URLSlugs('title', {update: true}));
postsSchema.plugin(crate, crateConfig);

mongoose.model('posts', postsSchema);
@achingbrain
Copy link
Owner

Could you post some example code of how you are deleting your model so I can attempt to replicate the problem?

@rgruesbeck
Copy link
Author

Hi achingbrain! thanks for the reply.
here is my delete method.

  delete:   function(id, query, cb){
    mongoose.model('posts').findByIdAndRemove(id, function(err){
      if (err){
        cb(null, err);
      } else {
        cb(null, 200);
      }
    });
  },

I also tried implementing the image delete myself but there seems to been an open issue with knox. so im guessing that is where the failure may be coming from?

Automattic/knox#244

Here is what i tried.

postsSchema.post('remove', function(post){
  var img = post.image;
  var org = img.original.url.substring(img.original.url.match('/images').index);
  var md = img.medium.url.substring(img.medium.url.match('/images').index);
  var sm = img.small.url.substring(img.small.url.match('/images').index);
  S3Client.deleteMultiple([org, md, sm], function(err, res){
    if (err){
      console.log(err);
    } else {
      console.log(res);
    }
  });
});

Im hoping this might be an aws configuration issue.

@SnidelyWhiplash
Copy link

Middleware hooks aren't run when using findByIdAndRemove() (among others) as those commands are issued directly to the DB.

See the note towards the bottom of Mongoose's middleware docs:

pre and post are not called for update operations executed directly on the database, including Model.update,.findByIdAndUpdate,.findOneAndUpdate, .findOneAndRemove,and .findByIdAndRemove. In order to utilize pre or post middleware, you should find() the document, and call the init, validate, save, or remove functions on the document. See explanation.

@rgruesbeck
Copy link
Author

Still having the same issue.
my delete method is now.

    Post.remove({_id: id}, function(err, post){
      if (err){
        cb(null, err);
      } else {
        cb(null, 200);
      }
    });

@SnidelyWhiplash
Copy link

Hmm, I'm not sure. According to remove() there is again a note stating:

This method sends a remove command directly to MongoDB, no Mongoose documents are involved. Because no Mongoose documents are involved, no middleware (hooks) are executed.

But that seems contradictory to what I see happening in Crate's tests; perhaps I'm reading the docs wrong.

One thing of note, and probably unrelated, is that in your examples you're passing along the err as the second param to the cb. It of course depends what your function definition is expecting, but convention is to receive the err as the first param, eg:

Post.remove({_id: id}, function (err, post){
  if (err) return cb(err);
  cb(null, 200);
});

@SnidelyWhiplash
Copy link

Maybe it's only on instances..?

Post.findById(id, function (err, post) {
  if (err) return cb(err);

  post.remove(function (err) {
    if (err) return cb(err);
    cb(null, 200);
  });
});

@achingbrain
Copy link
Owner

@rgruesbeck did you ever find out what was wrong? I haven't been able to replicate this issue, and I even started uploading files to S3 for real in the mongoose-crate-s3 tests.

@achingbrain
Copy link
Owner

Closing due to lack of response. @rgruesbeck please re-open if you come back to this.

@thebarndog
Copy link

I can also confirm this issue.

Here's my function for deleting a user:

 //delete an existing user
function deleteUser(params) {
    var deferred = q.defer();
    var response = { "status": 200, "deleted": null };

    if (typeof params._id === 'undefined') {
        response.status = 400;
        response.deleted = "invalid user id";
        deferred.resolve(response);
    }
   else {
        User.findById(params._id, function (err, user) {
            if (err) {
                 response.status = 400;
            response.deleted = err;
            deferred.resolve(response);
        }
        else {
            User.remove({'_id':params._id},function(err){
                if(err){
                    response.status = 400;
                    response.deleted = err;
                } else {
                    response.deleted = user;
                }
                deferred.resolve(response);
            }); 
        } 
    });
}

return deferred.promise;
}

My model is defined as:

var userSchema = new mongoose.Schema({
    facebookId  : { type: String, default: "", unique: true },
    twitterId   : { type: String, default: "", unique: true },
    firstName   : { type: String, trim: true, required: true },
    lastName    : { type: String, trim: true, required: true },
    email       : { type: String, lowercase: true, trim: true, required: true, unique: true },
    username    : { type: String, lowercase: true, trim: true, required: true, unique: true },
    created     : { type: Date, default: Date.now },
    updated     : { type: Date, default: Date.now },
    posts       : [{ type: mongoose.Schema.ObjectId, ref : 'Posts' }],
    comments    : [{ type: mongoose.Schema.ObjectId, ref : 'Comments'}],
    lofts       : [{ type: mongoose.Schema.ObjectId, ref : 'Lofts', childPath: 'members'}],
    likedPosts  : [{ type: mongoose.Schema.ObjectId, ref: 'Posts'}]
});

userSchema.plugin(relationship, {relationshipPathName: 'lofts', triggerMiddleware: true})
userSchema.plugin(deepPopulate, {});
userSchema.plugin(crate, {
    storage: new S3({
        key: constants.AWS_KEY,
        secret: constants.AWS_SECRET,
        bucket: 'swoopy-loft',
        acl: 'public-read',
        path: function(attachment){
            return '/user/' + path.basename(attachment.path); 
        }
    }),
fields: {
    image: {
        processor: new ImageMagick({
        tmpDir: '/tmp', // Where transformed files are placed before storage, defaults to os.tmpdir()
        formats: ['JPEG', 'GIF', 'PNG'], // Supported formats, defaults to ['JPEG', 'GIF', 'PNG', 'TIFF']
        transforms: {
            original: {
                resize: '750x750',
                format: '.png'
            },
            small: {
              resize: '250x250',
              format: '.png'
            },
            medium: {
              resize: '500x500',
              format: '.png'
            }
        }
      })
    }
}
});

When I make a call to my delete function, the model gets removed but the images remain on S3.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants