2017-12-08 7 views
1

저는 노드와 람다에 대해 매우 익숙합니다. 그래서 나는 아마도 약간의 실수를 저지르고있을 것입니다. s3 이벤트에서 파일을 가져 오는 node.js aws lambda 함수를 만들었습니다. 파일이 gzip이면 압축을 풀고 sftp 서버에 업로드 한 다음 동일한 sftp 서버에 sig 파일을 만들고 업로드합니다. 모든 것이 잘되면 작동하지만 오류를 올바르게 트리거하지 않는 것 같습니다.node.js에서 ssh2-sftp-client로 체인화 된 오류 콜백을 사용하지 않았습니다. 람다

sftp 명령은 then을 사용하여 연결되므로 이후 오류가 발생할 경우 오류가 발생할 것으로 예상됩니다. 예를 들어, sftp 서버를 끄면 sftp 클라이언트는 시간 초과 오류를 생성하지만 lambda는 콜백 오류를 보지 못하고 성공 만합니다. 로그에는 콘솔에 오류 출력이 표시되지만 나머지 .then() 항목 다음에 성공한 콜백이 사용 된 것으로 보입니다. 연결이 약속으로 올바르게 기록되어 있지 않습니까?

샘플 로그 :

... 
Starting SFTP 
Connected to sftp, starting sftp put for lastsub2.dat file. 
{ Error: Timed out while waiting for handshake 
    at Timeout._onTimeout (/var/task/node_modules/ssh2/lib/client.js:687:19) 
    at ontimeout (timers.js:386:14) 
    at tryOnTimeout (timers.js:250:5) 
    at Timer.listOnTimeout (timers.js:214:5) level: 'client-timeout' } 'Error occured during sftp relay.' 
END 

예제 코드 :

console.log('Loading function'); 
const aws = require('aws-sdk'); 
const s3 = new aws.S3({ 
    apiVersion: '2006-03-01' 
    }); 
const zlib = require('zlib'); 
const fs = require("fs"); 
const connSettings = { 
    host: 'xxx', 
    port: '22', 
    username: 'xxx', 
    password: 'xxx' 
}; 

exports.handler = function (event, context, callback) { 
    console.log('Received event:', JSON.stringify(event, null, 2)); 
    console.log('Bucket Name: ' + event.Records[0].s3.bucket.name); 
    console.log('Object Key: ' + decodeURIComponent(event.Records[0].s3.object.key.replace(/\+/g, ' '))); 
    const bucket = event.Records[0].s3.bucket.name; 
    const key = decodeURIComponent(event.Records[0].s3.object.key.replace(/\+/g, ' ')); 
    const params = { 
    Bucket: bucket, 
    Key: key, 
    }; 

    s3.getObject(params, (err, data) => { 
    if (err) { 
     console.log(err); 
     const message = 'Error getting object ${key} from bucket ${bucket}. Make sure they exist and your bucket is in the same region as this function.'; 
     console.log(message); 
     callback(message); 
    } else { 
     if (data.ContentType == 'application/x-gzip') { 
     console.log('CONTENT TYPE is application/x-gzip'); 
     var dataStream = s3.getObject(params).createReadStream().pipe(zlib.Unzip()); 
     console.log('Created unzip datastream'); 
     console.log('Starting SFTP'); 
     let Client = require('ssh2-sftp-client'); 
     let sftp = new Client(); 
     sftp.connect(connSettings) 
     .then(console.log('Connected to sftp, starting sftp put for ' + key.replace('.gz', '.dat') + ' file.')) 
     .then(() => { 
      console.log('Finished sftp put for ' + key.replace('.gz', '.dat') + ' file.'); 
      return sftp.put(dataStream, key.replace('.gz', '.dat'), true, 'utf-8'); 
     }).then(() => { 
      var sigFileName = key.replace('.gz', '.sig'); 
      var sigStream = fs.createWriteStream('/tmp/' + sigFileName); 
      sigStream.end(); 
      console.log('Created ' + sigFileName + ' sig file.'); 
      var readStream = fs.createReadStream('/tmp/' + sigFileName); 
      console.log('Uploaded ' + sigFileName + ' sig file.'); 
      return sftp.put(readStream, sigFileName, true, 'utf-8'); 
     }).then(() => { 
      console.log('Ended sftp connection.'); 
      return sftp.end(); 
     }) 
     .then(callback(null, 'Success')) 
     .catch ((err) => { 
      console.log(err, 'Error occured during sftp relay.'); 
      callback('Error', err); 
     }); 
     } else { 
     callback(null, 'Uploaded file not in gzip format, will not be processed.'); 
     } 
    } 
    }); 
}; 

답변

0

당신이 then()의 아무것도 반환하지 않기 때문에 일어나는 데 문제. 결과적으로 각 then()은 비동기 sftp 함수가 즉시 정의되지 않은 것으로 확인되기 때문에 반환 될 때까지 기다리지 않고 즉시 실행됩니다.

사용중인 sftp 라이브러리에 대해서는 언급하지 않았지만 약속이있는 것으로 가정하면 then()에서 해당 약속을 간단하게 반환 할 수 있습니다. 예를 들어

: 의견에 따라

.then(() => { 
     console.log('Finished sftp put for ' + key.replace('.gz', '.dat') + ' file.'); 
     // assumes stfp.put returns a promise, just return it into the chain 
     return sftp.put(dataStream, key.replace('.gz', '.dat'), true, 'utf-8'); 
    }) 

편집이 :

그런 다음에서 콜백을 호출 할 수 있어야한다()들. 편집중인 로그 출력을 살펴보면, 오류가있을 때 예상되는 것과 거의 같지 않습니다. 즉, 캐치로 점프합니다. 당신은 콘솔 출력을 얻고 있습니다. 'sftp에 연결되었습니다 ...'당신이 그걸 부르고 있기 때문에. 대신에 :

.then(console.log('Connected to sftp, starting sftp put for ' + key.replace('.gz', '.dat') + ' file.')) 

아마해야합니다 :

.then(() => console.log('Connected to sftp, starting sftp put for ' + key.replace('.gz', '.dat') + ' file.')) 

당신이 그것을 가지고하는 방법, 콘솔은 SFTP에서 오류가 반환되기 전에 기록합니다.

+0

안녕하세요, 귀하의 도움에 감사드립니다. https://github.com/jyu213/ssh2-sftp-client를 사용하고 있는데, 이는 각 항목에 대한 약속을 반환해야합니다. 위의 코드를 업데이트하여 명령을 반환했습니다. 그것은 로그를 변경했는데 (다음을 실행하지 않는 것처럼 보이지만) 여전히 성공을 리턴합니다. – cninsd

+0

좀 더 파기 한 후 핵심 문제는 약속에서 콜백을 사용하려고 시도하는 것입니다. 코드 구조를 재 작업해야한다고 생각합니다. – cninsd

+0

@cninsd 문제없이 콜백을 then()에서 호출 할 수 있어야합니다. 당신이 기대하는 바를 거의 출력하고있는 것처럼 보입니다. 위의 편집을 참조하십시오 ... –