Skip to content

Commit

Permalink
Merge pull request #79 from aalug/develop
Browse files Browse the repository at this point in the history
enhance job creation process with Elasticsearch indexing (#78)
  • Loading branch information
aalug committed Jul 29, 2023
2 parents 83a0caa + 28c4ccd commit 99e59f5
Show file tree
Hide file tree
Showing 11 changed files with 245 additions and 22 deletions.
37 changes: 37 additions & 0 deletions api/job.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"errors"
"fmt"
db "github.com/aalug/go-gin-job-search/db/sqlc"
"github.com/aalug/go-gin-job-search/esearch"
"github.com/aalug/go-gin-job-search/token"
"github.com/gin-gonic/gin"
"net/http"
Expand Down Expand Up @@ -122,6 +123,42 @@ func (server *Server) createJob(ctx *gin.Context) {
return
}

// creation was successful - create an elasticsearch index

// get the company name
companyName, err := server.store.GetCompanyNameByID(ctx, authEmployer.CompanyID)
if err != nil {
ctx.JSON(http.StatusInternalServerError, errorResponse(err))
return
}
var skills []string
// get the skill names from the job skills
for _, skill := range jobSkills {
skills = append(skills, skill.Skill)
}

j := esearch.Job{
ID: job.ID,
Title: job.Title,
Industry: job.Industry,
CompanyName: companyName,
Description: job.Description,
Location: job.Location,
SalaryMin: job.SalaryMin,
SalaryMax: job.SalaryMax,
Requirements: job.Requirements,
JobSkills: skills,
}

err = server.esDetails.client.IndexJobAsDocument(
int(server.esDetails.lastDocumentIndex),
j,
)
if err != nil {
ctx.JSON(http.StatusInternalServerError, errorResponse(err))
return
}

ctx.JSON(http.StatusCreated, newJobResponse(job, jobSkills))
}

Expand Down
150 changes: 139 additions & 11 deletions api/job_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import (
)

func TestCreateJobAPI(t *testing.T) {
employer, _, _ := generateRandomEmployerAndCompany(t)
employer, _, company := generateRandomEmployerAndCompany(t)

job := generateRandomJob()

Expand Down Expand Up @@ -52,7 +52,7 @@ func TestCreateJobAPI(t *testing.T) {
name string
body gin.H
setupAuth func(t *testing.T, r *http.Request, maker token.Maker)
buildStubs func(store *mockdb.MockStore)
buildStubs func(store *mockdb.MockStore, client *mockesearch.MockESearchClient)
checkResponse func(recorder *httptest.ResponseRecorder)
}{
{
Expand All @@ -61,7 +61,7 @@ func TestCreateJobAPI(t *testing.T) {
setupAuth: func(t *testing.T, r *http.Request, maker token.Maker) {
addAuthorization(t, r, maker, authorizationTypeBearer, employer.Email, time.Minute)
},
buildStubs: func(store *mockdb.MockStore) {
buildStubs: func(store *mockdb.MockStore, client *mockesearch.MockESearchClient) {
store.EXPECT().
GetEmployerByEmail(gomock.Any(), gomock.Eq(employer.Email)).
Times(1).
Expand Down Expand Up @@ -93,6 +93,26 @@ func TestCreateJobAPI(t *testing.T) {
ListJobSkillsByJobID(gomock.Any(), gomock.Eq(listSkillsParams)).
Times(1).
Return(jobSkills, nil)
store.EXPECT().
GetCompanyNameByID(gomock.Any(), gomock.Eq(employer.CompanyID)).
Times(1).
Return(company.Name, nil)
j := esearch.Job{
ID: job.ID,
Title: job.Title,
Industry: job.Industry,
CompanyName: company.Name,
Description: job.Description,
Location: job.Location,
SalaryMin: job.SalaryMin,
SalaryMax: job.SalaryMax,
Requirements: job.Requirements,
JobSkills: requiredSkills,
}
client.EXPECT().
IndexJobAsDocument(gomock.Eq(1), gomock.Eq(j)).
Times(1).
Return(nil)
},
checkResponse: func(recorder *httptest.ResponseRecorder) {
require.Equal(t, http.StatusCreated, recorder.Code)
Expand All @@ -105,7 +125,7 @@ func TestCreateJobAPI(t *testing.T) {
setupAuth: func(t *testing.T, r *http.Request, maker token.Maker) {
addAuthorization(t, r, maker, authorizationTypeBearer, employer.Email, time.Minute)
},
buildStubs: func(store *mockdb.MockStore) {
buildStubs: func(store *mockdb.MockStore, client *mockesearch.MockESearchClient) {
store.EXPECT().
GetEmployerByEmail(gomock.Any(), gomock.Eq(employer.Email)).
Times(1).
Expand All @@ -132,6 +152,12 @@ func TestCreateJobAPI(t *testing.T) {
ListJobSkillsByJobID(gomock.Any(), gomock.Any()).
Times(1).
Return([]db.ListJobSkillsByJobIDRow{}, sql.ErrConnDone)
store.EXPECT().
GetCompanyNameByID(gomock.Any(), gomock.Any()).
Times(0)
client.EXPECT().
IndexJobAsDocument(gomock.Any(), gomock.Any()).
Times(0)
},
checkResponse: func(recorder *httptest.ResponseRecorder) {
require.Equal(t, http.StatusInternalServerError, recorder.Code)
Expand All @@ -143,7 +169,7 @@ func TestCreateJobAPI(t *testing.T) {
setupAuth: func(t *testing.T, r *http.Request, maker token.Maker) {
addAuthorization(t, r, maker, authorizationTypeBearer, employer.Email, time.Minute)
},
buildStubs: func(store *mockdb.MockStore) {
buildStubs: func(store *mockdb.MockStore, client *mockesearch.MockESearchClient) {
store.EXPECT().
GetEmployerByEmail(gomock.Any(), gomock.Eq(employer.Email)).
Times(1).
Expand All @@ -169,6 +195,12 @@ func TestCreateJobAPI(t *testing.T) {
store.EXPECT().
ListJobSkillsByJobID(gomock.Any(), gomock.Any()).
Times(0)
store.EXPECT().
GetCompanyNameByID(gomock.Any(), gomock.Any()).
Times(0)
client.EXPECT().
IndexJobAsDocument(gomock.Any(), gomock.Any()).
Times(0)
},
checkResponse: func(recorder *httptest.ResponseRecorder) {
require.Equal(t, http.StatusInternalServerError, recorder.Code)
Expand All @@ -180,7 +212,7 @@ func TestCreateJobAPI(t *testing.T) {
setupAuth: func(t *testing.T, r *http.Request, maker token.Maker) {
addAuthorization(t, r, maker, authorizationTypeBearer, employer.Email, time.Minute)
},
buildStubs: func(store *mockdb.MockStore) {
buildStubs: func(store *mockdb.MockStore, client *mockesearch.MockESearchClient) {
store.EXPECT().
GetEmployerByEmail(gomock.Any(), gomock.Eq(employer.Email)).
Times(1).
Expand All @@ -195,6 +227,12 @@ func TestCreateJobAPI(t *testing.T) {
store.EXPECT().
ListJobSkillsByJobID(gomock.Any(), gomock.Any()).
Times(0)
store.EXPECT().
GetCompanyNameByID(gomock.Any(), gomock.Any()).
Times(0)
client.EXPECT().
IndexJobAsDocument(gomock.Any(), gomock.Any()).
Times(0)
},
checkResponse: func(recorder *httptest.ResponseRecorder) {
require.Equal(t, http.StatusInternalServerError, recorder.Code)
Expand All @@ -206,7 +244,7 @@ func TestCreateJobAPI(t *testing.T) {
setupAuth: func(t *testing.T, r *http.Request, maker token.Maker) {
addAuthorization(t, r, maker, authorizationTypeBearer, employer.Email, time.Minute)
},
buildStubs: func(store *mockdb.MockStore) {
buildStubs: func(store *mockdb.MockStore, client *mockesearch.MockESearchClient) {
store.EXPECT().
GetEmployerByEmail(gomock.Any(), gomock.Any()).
Times(1).
Expand All @@ -220,6 +258,83 @@ func TestCreateJobAPI(t *testing.T) {
store.EXPECT().
ListJobSkillsByJobID(gomock.Any(), gomock.Any()).
Times(0)
store.EXPECT().
GetCompanyNameByID(gomock.Any(), gomock.Any()).
Times(0)
client.EXPECT().
IndexJobAsDocument(gomock.Any(), gomock.Any()).
Times(0)
},
checkResponse: func(recorder *httptest.ResponseRecorder) {
require.Equal(t, http.StatusInternalServerError, recorder.Code)
},
},
{
name: "Internal Server Error GetCompanyNameByID",
body: requestBody,
setupAuth: func(t *testing.T, r *http.Request, maker token.Maker) {
addAuthorization(t, r, maker, authorizationTypeBearer, employer.Email, time.Minute)
},
buildStubs: func(store *mockdb.MockStore, client *mockesearch.MockESearchClient) {
store.EXPECT().
GetEmployerByEmail(gomock.Any(), gomock.Eq(employer.Email)).
Times(1).
Return(employer, nil)
store.EXPECT().
CreateJob(gomock.Any(), gomock.Any()).
Times(1).
Return(job, nil)
store.EXPECT().
CreateMultipleJobSkills(gomock.Any(), gomock.Any(), gomock.Any()).
Times(1).
Return(nil)
store.EXPECT().
ListJobSkillsByJobID(gomock.Any(), gomock.Any()).
Times(1).
Return(jobSkills, nil)
store.EXPECT().
GetCompanyNameByID(gomock.Any(), gomock.Any()).
Times(1).
Return("", sql.ErrConnDone)
client.EXPECT().
IndexJobAsDocument(gomock.Any(), gomock.Any()).
Times(0)
},
checkResponse: func(recorder *httptest.ResponseRecorder) {
require.Equal(t, http.StatusInternalServerError, recorder.Code)
},
},
{
name: "Internal Server Error IndexJobAsDocument",
body: requestBody,
setupAuth: func(t *testing.T, r *http.Request, maker token.Maker) {
addAuthorization(t, r, maker, authorizationTypeBearer, employer.Email, time.Minute)
},
buildStubs: func(store *mockdb.MockStore, client *mockesearch.MockESearchClient) {
store.EXPECT().
GetEmployerByEmail(gomock.Any(), gomock.Eq(employer.Email)).
Times(1).
Return(employer, nil)
store.EXPECT().
CreateJob(gomock.Any(), gomock.Any()).
Times(1).
Return(job, nil)
store.EXPECT().
CreateMultipleJobSkills(gomock.Any(), gomock.Any(), gomock.Any()).
Times(1).
Return(nil)
store.EXPECT().
ListJobSkillsByJobID(gomock.Any(), gomock.Any()).
Times(1).
Return(jobSkills, nil)
store.EXPECT().
GetCompanyNameByID(gomock.Any(), gomock.Any()).
Times(1).
Return(company.Name, nil)
client.EXPECT().
IndexJobAsDocument(gomock.Any(), gomock.Any()).
Times(1).
Return(errors.New("some error"))
},
checkResponse: func(recorder *httptest.ResponseRecorder) {
require.Equal(t, http.StatusInternalServerError, recorder.Code)
Expand All @@ -234,7 +349,7 @@ func TestCreateJobAPI(t *testing.T) {
setupAuth: func(t *testing.T, r *http.Request, maker token.Maker) {
addAuthorization(t, r, maker, authorizationTypeBearer, employer.Email, time.Minute)
},
buildStubs: func(store *mockdb.MockStore) {
buildStubs: func(store *mockdb.MockStore, client *mockesearch.MockESearchClient) {
store.EXPECT().
GetEmployerByEmail(gomock.Any(), gomock.Any()).
Times(0)
Expand All @@ -247,6 +362,12 @@ func TestCreateJobAPI(t *testing.T) {
store.EXPECT().
ListJobSkillsByJobID(gomock.Any(), gomock.Any()).
Times(0)
store.EXPECT().
GetCompanyNameByID(gomock.Any(), gomock.Any()).
Times(0)
client.EXPECT().
IndexJobAsDocument(gomock.Any(), gomock.Any()).
Times(0)
},
checkResponse: func(recorder *httptest.ResponseRecorder) {
require.Equal(t, http.StatusBadRequest, recorder.Code)
Expand All @@ -267,7 +388,7 @@ func TestCreateJobAPI(t *testing.T) {
setupAuth: func(t *testing.T, r *http.Request, maker token.Maker) {
addAuthorization(t, r, maker, authorizationTypeBearer, employer.Email, time.Minute)
},
buildStubs: func(store *mockdb.MockStore) {
buildStubs: func(store *mockdb.MockStore, client *mockesearch.MockESearchClient) {
store.EXPECT().
GetEmployerByEmail(gomock.Any(), gomock.Any()).
Times(0)
Expand All @@ -280,6 +401,12 @@ func TestCreateJobAPI(t *testing.T) {
store.EXPECT().
ListJobSkillsByJobID(gomock.Any(), gomock.Any()).
Times(0)
store.EXPECT().
GetCompanyNameByID(gomock.Any(), gomock.Any()).
Times(0)
client.EXPECT().
IndexJobAsDocument(gomock.Any(), gomock.Any()).
Times(0)
},
checkResponse: func(recorder *httptest.ResponseRecorder) {
require.Equal(t, http.StatusBadRequest, recorder.Code)
Expand All @@ -294,9 +421,10 @@ func TestCreateJobAPI(t *testing.T) {
defer ctrl.Finish()

store := mockdb.NewMockStore(ctrl)
tc.buildStubs(store)
client := mockesearch.NewMockESearchClient(ctrl)
tc.buildStubs(store, client)

server := newTestServer(t, store, nil)
server := newTestServer(t, store, client)
recorder := httptest.NewRecorder()

data, err := json.Marshal(tc.body)
Expand Down
4 changes: 4 additions & 0 deletions api/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ func newTestServer(t *testing.T, store db.Store, client esearch.ESearchClient) *
server, err := NewServer(config, store, client)
require.NoError(t, err)

if client != nil {
server.esDetails.lastDocumentIndex = 1
}

return server
}

Expand Down
15 changes: 15 additions & 0 deletions db/mock/store.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions db/queries/company.sql
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@ SELECT *
FROM companies
WHERE id = $1;

-- name: GetCompanyNameByID :one
SELECT name
FROM companies
WHERE id = $1;

-- name: GetCompanyByName :one
SELECT *
FROM companies
Expand Down
13 changes: 13 additions & 0 deletions db/sqlc/company.sql.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 99e59f5

Please sign in to comment.