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

Remote support #139

Merged
merged 11 commits into from
Feb 12, 2017
Merged

Remote support #139

merged 11 commits into from
Feb 12, 2017

Conversation

levrado
Copy link
Contributor

@levrado levrado commented Jan 10, 2017

Added support for jobType as discussed in #73 with a remote job type

basically it adds the following support:

if user passed job_type: 1 in the create job json, it allows her/him to specify remote_properties:

  • url, allows to configure to what url to send the request
  • method, specifying the method to use
  • body, allows adding a body to the http request
  • headers, a list of headers as jsons ({"key": "k", "value": "v"}
  • timeout, after how long to declare the request as failure if there is no response
  • expected_response_codes, a list of ints to specify which response codes are declared as success

all params have default values and all except for url are optional

@levrado
Copy link
Contributor Author

levrado commented Jan 10, 2017

@ajvb Hi, it seems PR failed for some failure communicating with coveralls and not from my changes, could you please check and rerun?
the message:
Bad response status from coveralls: 422 - {"message":"Couldn't find a repository matching this job.","error":true}

@ajvb
Copy link
Owner

ajvb commented Jan 10, 2017

@levrado Thank you for the PR! This is looking great so far.

  1. First off, could we make sure to add comments to some of the new types and functions? As well, can we add some tests that hit a mock http server?

  2. In regards to the coveralls, lets just rip it out in this PR. It has caused me tons of problems, and its easier to just run a coverage test locally.

You will want to delete everything from the test section except these lines: https://github.com/ajvb/kala/blob/master/circle.yml#L26-L28

@levrado levrado changed the title Remote support (WIP) Remote support Jan 10, 2017
@levrado
Copy link
Contributor Author

levrado commented Jan 10, 2017

@ajvb added tests, comments and removed coveralls

@@ -94,6 +126,11 @@ type Metadata struct {
LastAttemptedRun time.Time `json:"last_attempted_run"`
}

type Header struct {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a reason you choose to use a custom type rather than http.Header? https://golang.org/pkg/net/http/#Header

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the difference is in how the user request will look like

currently:

{"headers": [{"Content-Type": "text/plain"}]

vs using Google's:

{"headers": {"Content-Type": ["text/plain"]}}

the first seemed a little more natural

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd much prefer the use of http.Header. No need to re-invent the wheel.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, please use the existing http.Header type

@@ -432,3 +469,18 @@ func (j *Job) ShouldStartWaiting() bool {
}
return true
}

func (j *Job) validation() error {
if j.JobType == 0 && (j.Name == "" || j.Command == "") {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we use the constants defined rather than 0 and 1?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oops, sure :)

log.Errorf(ErrInvalidJob.Error())
return ErrInvalidJob
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't j.validation() be called here instead? Or is it being called elsewhere and I just don't see it?

@levrado
Copy link
Contributor Author

levrado commented Jan 22, 2017

@ajvb can you please update me the status of the review? tnx

@ajvb
Copy link
Owner

ajvb commented Jan 25, 2017

hey @levrado, sorry for the delay. I will review today.

Copy link
Owner

@ajvb ajvb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two small changes. After those are done I believe it will be ready to merge.

@@ -94,6 +126,11 @@ type Metadata struct {
LastAttemptedRun time.Time `json:"last_attempted_run"`
}

type Header struct {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd much prefer the use of http.Header. No need to re-invent the wheel.

LocalJob jobType = 0 + iota
RemoteJob
)

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we add a comment describing RemoteProperties, can be the same as the above one. Mostly for the godocs generated html.

@ajvb
Copy link
Owner

ajvb commented Jan 25, 2017

@elimisteve Would love a 👍 from you if you have the time :)

Copy link
Contributor

@elimisteve elimisteve left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm just looking at this quickly, so I'm not seeing the big picture, but other than my comments just given, each line looks good individually :-)

"url": "http://example.com",
},
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Apply gofmt to this

ErrInvalidJob = errors.New("Invalid Job. Job's must contain a Name and a Command field")
ErrInvalidJob = errors.New("Invalid Local Job. Job's must contain a Name and a Command field")
ErrInvalidRemoteJob = errors.New("Invalid Remote Job. Job's must contain a Name and a url field")
ErrInvalidJobType = errors.New("Invalid Job type. Types supported: 0 for local and 1 for remote")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, use gofmt please

JobType jobType `json:"type"`

// Custom properties for the remote job type
RemoteProperties RemoteProperties `json:"remote_proporties"`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo: should be remote_propErties, not propOrties

LocalJob jobType = 0 + iota
RemoteJob
)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@levrado Good idea, but you should be able to just say iota rather than 0 + iota

@@ -94,6 +126,11 @@ type Metadata struct {
LastAttemptedRun time.Time `json:"last_attempted_run"`
}

type Header struct {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, please use the existing http.Header type

} else {
return nil
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reduce code duplication by turning

		log.Errorf(ErrInvalidJob.Error())
		return ErrInvalidJob

into

err = ErrInvalidJob

then finish with

log.Errorf(err.Error())

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(and use that same trick for every else if clause)

}
// Create a new header for our job properties and set the default header
j.job.RemoteProperties.Headers = make(http.Header)
j.job.RemoteProperties.Headers.Set("Content-Type", jsonContentType)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These 2 lines can be combined into just

j.job.RemoteProperties.Headers = http.Header["Content-Type"] = []string{jsonContentType}

Copy link
Contributor Author

@levrado levrado Jan 26, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

http.Header["Content-Type"] is a list of strings and j.job.RemoteProperties.Headers is a map of string[]string, assignment is not possible

plus it's not very readable friendly to have 2 assignment operators on one line in my opinion

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops, I meant

j.job.RemoteProperties.Headers = http.Header{"Content-Type": []string{jsonContentType}}

@levrado
Copy link
Contributor Author

levrado commented Jan 26, 2017

@ajvb @elimisteve done changing according to pr comments

circleci is complaining on a data race that i can't seem to replicate on my computer (although i did found a problem in TestOneOffJobs in job_test which i fixed by moving the locking 2 lines up)

could you please have a look and tell me if the error happening with the current master on circleci?

return errors.New(res.Status)
}
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On line 145, CircleCI says

args, err := shParser.Parse(j.job.Command)

is racing with some other line. Investigating now...

@elimisteve
Copy link
Contributor

@levrado Are there any tests that share state? I don't see anything being run concurrently at all, so I'm not sure how and where the race could be coming from.

)

// Run executes the Job's command, collects metadata around the success
// Run calls the appropiate run function, collects metadata around the success
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

*appropRiate


// responseTimeout sets a default timeout if none specified
func (j *JobRunner) responseTimeout() time.Duration {
responseTimeout := j.job.RemoteProperties.Timeout
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@levrado @ajvb Eventually making this a duration rather than an untyped number that represents seconds would be good

@elimisteve
Copy link
Contributor

@levrado Instead of calling every job mock_job, could you number them, or include a high-precision timestamp so that we can tell which mock job is involved in the race?

I don't see much concurrent happening unless the job is unscheduled, in which case it runs immediately:

kala/job/job.go

Line 163 in cd5ec29

go j.Run(cache)

@levrado
Copy link
Contributor Author

levrado commented Jan 26, 2017

@elimisteve the tests that I wrote are with "mock_remote_job" in the job name, those are not my tests that are failing

also it's not happening on my computer (running the same command as circleci) and didn't failed on circleci 2 weeks ago as well.

is it possible to rerun the master branch on circleci? to eliminate that those are my changes causing it

@elimisteve
Copy link
Contributor

Found it: shParser is being used concurrently, which isn't safe: a0c7cc9#commitcomment-20631329

@levrado
Copy link
Contributor Author

levrado commented Jan 26, 2017

@elimisteve good catch, weird that it passed ok till now for you guys

changed it to not be reused but be created on every new command run

@elimisteve
Copy link
Contributor

@ajvb @levrado I'm not seeing the entire big picture, but in the small at least, LGTM :-) 👍

Copy link
Owner

@ajvb ajvb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good! Thanks again @levrado

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

Successfully merging this pull request may close these issues.

3 participants