-
Notifications
You must be signed in to change notification settings - Fork 4
CON-1896 jobs progress #24
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
Open
az-smartling
wants to merge
7
commits into
master
Choose a base branch
from
CON-1896_jobs_progress
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
7 commits
Select commit
Hold shift + click to select a range
ec19f74
CON-1896 jobs progress
az-smartling 6cb1a9c
fixed jobBasePath
az-smartling 535aa85
updated make slice
az-smartling 3d4239a
CR changes
az-smartling 98292be
CR changes
az-smartling 79d0084
Merge branch 'master' into CON-1896_jobs_progress
az-smartling e8c40c9
Use the same var names. More usage of path.Join.
az-smartling File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,56 @@ | ||
| package job | ||
|
|
||
| // GetJobResponse defines get job response | ||
| type GetJobResponse struct { | ||
| TranslationJobUID string | ||
| JobName string | ||
| } | ||
|
|
||
| // FindFirstJobByName finds the first job by name from the list of jobs | ||
| func FindFirstJobByName(jobs []GetJobResponse, name string) (GetJobResponse, bool) { | ||
| for _, job := range jobs { | ||
| if job.JobName == name { | ||
| return job, true | ||
| } | ||
| } | ||
| return GetJobResponse{}, false | ||
| } | ||
|
|
||
| type getJobResponse struct { | ||
| Response struct { | ||
| Code string `json:"code"` | ||
| Data struct { | ||
| JobName string `json:"jobName"` | ||
| TranslationJobUID string `json:"translationJobUid"` | ||
| } `json:"data"` | ||
| } `json:"response"` | ||
| } | ||
| type getJobsResponse struct { | ||
| Response struct { | ||
| Code string `json:"code"` | ||
| Data struct { | ||
| Items []struct { | ||
| JobName string `json:"jobName"` | ||
| TranslationJobUID string `json:"translationJobUid"` | ||
| } `json:"items"` | ||
| } `json:"data"` | ||
| } `json:"response"` | ||
| } | ||
|
|
||
| func toGetJobResponse(r getJobResponse) GetJobResponse { | ||
| return GetJobResponse{ | ||
| TranslationJobUID: r.Response.Data.TranslationJobUID, | ||
| JobName: r.Response.Data.JobName, | ||
| } | ||
| } | ||
|
|
||
| func toGetJobsResponse(r getJobsResponse) []GetJobResponse { | ||
| res := make([]GetJobResponse, len(r.Response.Data.Items)) | ||
| for i, job := range r.Response.Data.Items { | ||
| res[i] = GetJobResponse{ | ||
| TranslationJobUID: job.TranslationJobUID, | ||
| JobName: job.JobName, | ||
| } | ||
| } | ||
| return res | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,66 @@ | ||
| package job | ||
|
|
||
| import ( | ||
| "encoding/json" | ||
| "fmt" | ||
| ) | ||
|
|
||
| // GetJobProgressResponse defines get job progress response | ||
| type GetJobProgressResponse struct { | ||
| TranslationJobUID string | ||
| TotalWordCount uint32 | ||
| PercentComplete uint32 | ||
| Json []byte | ||
| } | ||
| type getJobProgressResponse struct { | ||
| Response struct { | ||
| Code string `json:"code"` | ||
| Data struct { | ||
| ContentProgressReport []struct { | ||
| Progress struct { | ||
| PercentComplete int `json:"percentComplete"` | ||
| TotalWordCount int `json:"totalWordCount"` | ||
| } `json:"progress"` | ||
| TargetLocaleDescription string `json:"targetLocaleDescription"` | ||
| TargetLocaleId string `json:"targetLocaleId"` | ||
| UnauthorizedProgressReport struct { | ||
| StringCount int `json:"stringCount"` | ||
| WordCount int `json:"wordCount"` | ||
| } `json:"unauthorizedProgressReport"` | ||
| WorkflowProgressReportList []struct { | ||
| WorkflowName string `json:"workflowName"` | ||
| WorkflowStepSummaryReportItemList []struct { | ||
| StringCount int `json:"stringCount"` | ||
| WordCount int `json:"wordCount"` | ||
| WorkflowStepName string `json:"workflowStepName"` | ||
| WorkflowStepType string `json:"workflowStepType"` | ||
| WorkflowStepUid string `json:"workflowStepUid"` | ||
| } `json:"workflowStepSummaryReportItemList"` | ||
| WorkflowUid string `json:"workflowUid"` | ||
| } `json:"workflowProgressReportList"` | ||
| } `json:"contentProgressReport"` | ||
| Progress struct { | ||
| PercentComplete uint32 `json:"percentComplete"` | ||
| TotalWordCount uint32 `json:"totalWordCount"` | ||
| } `json:"progress"` | ||
| SummaryReport []struct { | ||
| StringCount int `json:"stringCount"` | ||
| WordCount int `json:"wordCount"` | ||
| WorkflowStepName string `json:"workflowStepName"` | ||
| } `json:"summaryReport"` | ||
| } `json:"data"` | ||
| } `json:"response"` | ||
| } | ||
|
|
||
| func toGetJobProgressResponse(r getJobProgressResponse, translationJobUID string) (GetJobProgressResponse, error) { | ||
| data, err := json.Marshal(r.Response.Data) | ||
| if err != nil { | ||
| return GetJobProgressResponse{}, fmt.Errorf("failed to marshal job progress response: %w", err) | ||
| } | ||
| return GetJobProgressResponse{ | ||
| TranslationJobUID: translationJobUID, | ||
| TotalWordCount: r.Response.Data.Progress.TotalWordCount, | ||
| PercentComplete: r.Response.Data.Progress.PercentComplete, | ||
| Json: data, | ||
| }, nil | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -4,15 +4,19 @@ import ( | |
| "encoding/json" | ||
| "fmt" | ||
| "io" | ||
| "net/url" | ||
| "path" | ||
|
|
||
| smclient "github.com/Smartling/api-sdk-go/helpers/sm_client" | ||
| ) | ||
|
|
||
| const jobBasePath = "/job-batches-api/v2/projects/" | ||
| const jobBasePath = "/jobs-api/v3/projects/" | ||
|
|
||
| // Job defines the job behaviour | ||
| type Job interface { | ||
| GetJob(projectID string, translationJobUID string) (GetJobResponse, error) | ||
| Get(projectID string, translationJobUID string) (GetJobResponse, error) | ||
| GetAllByName(projectID, name string) (jobs []GetJobResponse, err error) | ||
| Progress(projectID string, translationJobUID string) (GetJobProgressResponse, error) | ||
| } | ||
|
|
||
| // NewJob returns new Job implementation | ||
|
|
@@ -29,27 +33,89 @@ func newHttpJob(client *smclient.Client) httpJob { | |
| return httpJob{client: client} | ||
| } | ||
|
|
||
| // GetJob gets a job related info | ||
| func (h httpJob) GetJob(projectID string, translationJobUID string) (GetJobResponse, error) { | ||
| url := jobBasePath + projectID + "/jobs/" + translationJobUID | ||
| // Get gets a job related info | ||
| func (h httpJob) Get(projectID string, translationJobUID string) (GetJobResponse, error) { | ||
| reqURL := path.Join(jobBasePath, url.PathEscape(projectID), "jobs", url.PathEscape(translationJobUID)) | ||
| var response getJobResponse | ||
| rawMessage, code, err := h.client.Get(url, nil) | ||
| rawMessage, code, err := h.client.Get(reqURL, nil) | ||
| if err != nil { | ||
| return GetJobResponse{}, err | ||
| } | ||
| defer func() { | ||
| if err := rawMessage.Close(); err != nil { | ||
| h.client.Logger.Debugf("failed to close response body: %v", err) | ||
| } | ||
| }() | ||
| body, err := io.ReadAll(rawMessage) | ||
| if err != nil { | ||
| return GetJobResponse{}, fmt.Errorf("failed to read response body: %w", err) | ||
| } | ||
| if code != 200 { | ||
| body, _ := io.ReadAll(rawMessage) | ||
| h.client.Logger.Debugf("response body: %s\n", body) | ||
| return GetJobResponse{}, fmt.Errorf("unexpected response code: %d", code) | ||
| } | ||
| if err := json.Unmarshal(body, &response); err != nil { | ||
| return GetJobResponse{}, fmt.Errorf("failed to unmarshal response: %w", err) | ||
| } | ||
| return toGetJobResponse(response), nil | ||
| } | ||
|
|
||
| // GetAllByName gets all jobs of a project by name | ||
| func (h httpJob) GetAllByName(projectID, name string) ([]GetJobResponse, error) { | ||
| reqURL := path.Join(jobBasePath, url.PathEscape(projectID), "jobs") | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: In the method above you call variable |
||
|
|
||
| params := url.Values{} | ||
| params.Set("jobName", name) | ||
|
|
||
| rawMessage, code, err := h.client.Get(reqURL, params) | ||
| if err != nil { | ||
| return nil, err | ||
| } | ||
| defer func() { | ||
| if err := rawMessage.Close(); err != nil { | ||
| h.client.Logger.Debugf("failed to close response body: %v", err) | ||
| } | ||
| }() | ||
| body, err := io.ReadAll(rawMessage) | ||
| if err != nil { | ||
| return nil, fmt.Errorf("failed to read response body: %w", err) | ||
| } | ||
| if code != 200 { | ||
| h.client.Logger.Debugf("response body: %s\n", body) | ||
| return nil, fmt.Errorf("unexpected response code: %d", code) | ||
| } | ||
| var res getJobsResponse | ||
| if err := json.Unmarshal(body, &res); err != nil { | ||
| return nil, fmt.Errorf("failed to unmarshal response: %w", err) | ||
| } | ||
| jobs := toGetJobsResponse(res) | ||
|
|
||
| return jobs, nil | ||
| } | ||
|
|
||
| // Progress returns a job related progress | ||
| func (h httpJob) Progress(projectID string, translationJobUID string) (GetJobProgressResponse, error) { | ||
| reqURL := path.Join(jobBasePath, url.PathEscape(projectID), "jobs", url.PathEscape(translationJobUID), "progress") | ||
| var response getJobProgressResponse | ||
| rawMessage, code, err := h.client.Get(reqURL, nil) | ||
| if err != nil { | ||
| return GetJobProgressResponse{}, err | ||
| } | ||
| defer func() { | ||
| if err := rawMessage.Close(); err != nil { | ||
| h.client.Logger.Debugf("failed to close response body: %v", err) | ||
| } | ||
| }() | ||
| body, err := io.ReadAll(rawMessage) | ||
| if err != nil { | ||
| body, _ := io.ReadAll(rawMessage) | ||
| return GetJobProgressResponse{}, fmt.Errorf("failed to read response body: %w", err) | ||
| } | ||
| if code != 200 { | ||
| h.client.Logger.Debugf("response body: %s\n", body) | ||
| return GetJobResponse{}, err | ||
| return GetJobProgressResponse{}, fmt.Errorf("unexpected response code: %d", code) | ||
| } | ||
| if err := json.Unmarshal(body, &response); err != nil { | ||
| return GetJobResponse{}, fmt.Errorf("failed to unmarshal response: %w", err) | ||
| return GetJobProgressResponse{}, fmt.Errorf("failed to unmarshal response: %w", err) | ||
| } | ||
| return toGetJobResponse(response), nil | ||
| return toGetJobProgressResponse(response, translationJobUID) | ||
| } | ||
This file was deleted.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you please research how to add validation for input parameters? An example for this specific case: we must check that parameters are not empty and
projectIDfollows specific patterns.P.S. Well, I do not want to broaden the scope of this ticket/PR. Let's make a Jira ticket for research on how to use a declarative approach for validation (rather than imerative).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can do simple checks. If var is not empty etc. More complex checks could bring errors when in SDK var is invalid when in API the var is valid.