Skip to content

Commit

Permalink
BCDA-8234: Import a single CCLF file zip when triggered by BFD S3 not…
Browse files Browse the repository at this point in the history
…ifications (#968)

## 🎫 Ticket

https://jira.cms.gov/browse/BCDA-8234

## 🛠 Changes

- Update lambda entrypoint to only import the CCLF file that caused the
lambda instance to start
- Consolidate "valid2" test zips into a single zip to match production
format (CCLF0 and CCLF8 files come in a single zip, not split across
multiple zips)

## ℹ️ Context

To avoid race conditions, we would like to ensure that each lambda
instance imports only the CCLF file that started the lambda instance via
S3 notifications. This ensures that each lambda instance has exactly one
file responsibility, and there are no conflicts between lambdas
attempting to import the same file.

Note that this technically allows us to still process entire directories
at once by manually sending events in the AWS Console with just the
directory name, instead of the path for a single file.

## 🧪 Validation

- Updated unit tests
  • Loading branch information
kyeah committed Jul 5, 2024
1 parent 6276264 commit 777b548
Show file tree
Hide file tree
Showing 7 changed files with 51 additions and 7 deletions.
41 changes: 41 additions & 0 deletions bcda/cclf/s3_fileprocessor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,47 @@ func (s *S3ProcessorTestSuite) TestLoadCclfFiles() {
}
}

func (s *S3ProcessorTestSuite) TestLoadCclfFiles_SingleFile() {
cmsID, key := "A0001", metadataKey{perfYear: 18, fileType: models.FileTypeDefault}
tests := []struct {
path string
filename string
numCCLFFiles int // Expected count for the cmsID, perfYear above
skipped int
failure int
numCCLF0 int // Expected count for the cmsID, perfYear above
numCCLF8 int // Expected count for the cmsID, perfYear above
}{
{"cclf/archives/valid2/", "T.BCD.A0001.ZCY18.D181120.T1000000", 2, 0, 0, 1, 1},
}

for _, tt := range tests {
s.T().Run(tt.path, func(t *testing.T) {
bucketName, cleanup := testUtils.CopyToS3(s.T(), filepath.Join(s.basePath, tt.path))
defer cleanup()

cclfMap, skipped, failure, err := s.processor.LoadCclfFiles(filepath.Join(bucketName, tt.path, tt.filename))
cclfFiles := cclfMap[cmsID][key]
assert.NoError(t, err)
assert.Equal(t, tt.skipped, skipped)
assert.Equal(t, tt.failure, failure)
assert.Equal(t, tt.numCCLFFiles, len(cclfFiles))
var numCCLF0, numCCLF8 int
for _, cclfFile := range cclfFiles {
if cclfFile.cclfNum == 0 {
numCCLF0++
} else if cclfFile.cclfNum == 8 {
numCCLF8++
} else {
assert.Fail(t, "Unexpected CCLF num received %d", cclfFile.cclfNum)
}
}
assert.Equal(t, tt.numCCLF0, numCCLF0)
assert.Equal(t, tt.numCCLF8, numCCLF8)
})
}
}

func (s *S3ProcessorTestSuite) TestLoadCclfFiles_InvalidPath() {
cclfMap, skipped, failure, err := s.processor.LoadCclfFiles("foo")
assert.ErrorContains(s.T(), err, "NoSuchBucket: The specified bucket does not exist")
Expand Down
6 changes: 4 additions & 2 deletions bcda/lambda/cclf/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,10 @@ func cclfImportHandler(ctx context.Context, sqsEvent events.SQSEvent) (string, e
return "", err
}

dir := bcdaaws.ParseS3Directory(e.S3.Bucket.Name, e.S3.Object.Key)
return handleCclfImport(s3AssumeRoleArn, dir)
// Send the entire filepath into the CCLF Importer so we are only
// importing the one file that was sent in the trigger.
filepath := fmt.Sprintf("%s/%s", e.S3.Bucket.Name, e.S3.Object.Key)
return handleCclfImport(s3AssumeRoleArn, filepath)
}
}

Expand Down
11 changes: 6 additions & 5 deletions bcda/lambda/cclf/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ func TestCclfImportMainSuite(t *testing.T) {
}

func (s *CclfImportMainSuite) TestImportCCLFDirectory() {
targetACO := "A0002"
targetACO := "A0001"
assert := assert.New(s.T())

env := uuid.NewUUID()
Expand All @@ -42,14 +42,15 @@ func (s *CclfImportMainSuite) TestImportCCLFDirectory() {

type test struct {
path string
filename string
err error
expectedLogs []string
}

tests := []test{
{path: "../../../shared_files/cclf/archives/valid2/", expectedLogs: []string{"Successfully imported 2 files.", "Failed to import 0 files.", "Skipped 0 files."}},
{path: "../../../shared_files/cclf/archives/invalid_bcd/", err: errors.New("one or more files failed to import correctly"), expectedLogs: []string{}},
{path: "../../../shared_files/cclf/archives/skip/", expectedLogs: []string{"Successfully imported 0 files.", "Failed to import 0 files.", "Skipped 0 files."}},
{path: "../../../shared_files/cclf/archives/valid2/", filename: "cclf/archives/valid2/T.BCD.A0001.ZCY18.D181120.T1000000", expectedLogs: []string{"Successfully imported 2 files.", "Failed to import 0 files.", "Skipped 0 files."}},
{path: "../../../shared_files/cclf/archives/invalid_bcd/", filename: "cclf/archives/invalid_bcd/P.BCD.A0009.ZCY18.D181120.T0001000", err: errors.New("one or more files failed to import correctly"), expectedLogs: []string{}},
{path: "../../../shared_files/cclf/archives/skip/", filename: "cclf/archives/skip/T.BCD.ACOB.ZC0Y18.D181120.T0001000", expectedLogs: []string{"Successfully imported 0 files.", "Failed to import 0 files.", "Skipped 0 files."}},
}

for _, tc := range tests {
Expand All @@ -59,7 +60,7 @@ func (s *CclfImportMainSuite) TestImportCCLFDirectory() {
path, cleanup := testUtils.CopyToS3(s.T(), tc.path)
defer cleanup()

res, err := cclfImportHandler(context.Background(), testUtils.GetSQSEvent(s.T(), path, "fake_filename"))
res, err := cclfImportHandler(context.Background(), testUtils.GetSQSEvent(s.T(), path, tc.filename))

if tc.err == nil {
assert.Nil(err)
Expand Down
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.

0 comments on commit 777b548

Please sign in to comment.