static_fontdir = $(staticdir)/font
dist_static_images_DATA = \
- src/static/images/icons/build-dependency_error.png \
src/static/images/icons/build-dispatching.png \
src/static/images/icons/build-failed.png \
src/static/images/icons/build-finished.png \
remove = True
for job in self.jobs:
- if job.state in ("new", "pending", "running", "dependency_error"):
+ if job.state in ("pending", "running"):
job.state = "aborted"
# If this build is in a repository, it will leave it.
break
def check_build_dependencies(self):
- jobs = self.backend.jobs._get_jobs("SELECT * FROM jobs \
- WHERE state = 'new' OR \
- (state = 'dependency_error' AND time_finished < NOW() - '5 minutes'::interval) \
- ORDER BY time_finished LIMIT 50")
+ # Check all jobs that have never being checked before
+ self._check_build_dependencies("SELECT * FROM jobs \
+ WHERE state = %s AND dependency_check_succeeded IS NULL \
+ ORDER BY time_created", "pending")
+
+ # Redo the check for all jobs that have recently failed
+ self._check_build_dependencies("SELECT * FROM jobs \
+ WHERE state = %s AND dependency_check_succeeeded IS FALSE \
+ AND dependency_check_at < NOW() - '5 minutes'::interval \
+ ORDER BY dependency_check_at", "pending")
+
+ def _check_build_dependencies(self, query, *args):
+ jobs = self.backend.jobs._get_jobs(query, *args)
for job in jobs:
with self.db.transaction():
- # Resolve the dependencies
- job.resolvdep()
\ No newline at end of file
+ job.resolvdep()
self._set_attribute("state", state)
# Log the event.
- if log and not state == "new":
+ if log:
self.log("state_change", state=state, user=user)
# Always clear the message when the status is changed.
# Set start time.
self._set_attribute("time_started", datetime.datetime.utcnow())
- elif state in ("aborted", "dependency_error", "finished", "failed"):
+ elif state in ("aborted", "finished", "failed"):
self._set_attribute("time_finished", datetime.datetime.utcnow())
# Send messages to the user.
state = property(get_state, set_state)
- @property
- def message(self):
- return self.data.message
+ def set_message(self, message):
+ self._set_attribute("message", "%s" % message)
+
+ message = property(lambda s: s.data.message, set_message)
+ # XXX DEPRECATED
def update_message(self, message):
- self._set_attribute("message", message)
+ self.message = message
def get_builder(self):
if self.data.builder_id:
return "\n\n".join(confs)
+ def set_dependency_check_succeeded(self, value):
+ self._set_attribute("dependency_check_succeeded", value)
+ self._set_attribute("dependency_check_at", datetime.datetime.utcnow())
+
+ # Reset the message
+ if value is True:
+ self.message = None
+
+ dependency_check_succeeded = property(
+ lambda s: s.data.dependency_check_succeeded,
+ set_dependency_check_succeeded)
+
def resolvdep(self):
config = pakfire.config.Config(files=["general.conf"])
config.parse(self.get_config(local=True))
# Catch dependency errors and log the problem string.
except DependencyError, e:
- self.state = "dependency_error"
+ self.dependency_check_succeeded = False
self.update_message("%s" % e)
+ # The dependency check has succeeded
else:
- # If the build dependencies can be resolved, we set the build in
- # pending state.
- if solver.status is True:
- if self.state in ("failed",):
- return
-
- self.state = "pending"
+ self.dependency_check_succeeded = True
id integer NOT NULL,
uuid text NOT NULL,
build_id integer NOT NULL,
- state text DEFAULT 'new'::text NOT NULL,
+ state text DEFAULT 'pending'::text NOT NULL,
arch text NOT NULL,
time_created timestamp without time zone DEFAULT now() NOT NULL,
time_started timestamp without time zone,
aborted_state integer DEFAULT 0 NOT NULL,
message text,
test boolean DEFAULT true NOT NULL,
- superseeded_by integer
+ superseeded_by integer,
+ dependency_check_succeeded boolean,
+ dependency_check_at timestamp without time zone,
+ CONSTRAINT jobs_states CHECK ((state = ANY (ARRAY['pending'::text, 'running'::text, 'finished'::text, 'aborted'::text, 'download_error'::text, 'failed'::text])))
);
rank() OVER (ORDER BY (NOT jobs.test), builds.priority DESC, jobs.time_created) AS rank
FROM (jobs
LEFT JOIN builds ON ((jobs.build_id = builds.id)))
- WHERE (jobs.state = 'pending'::text)
+ WHERE ((jobs.state = 'new'::text) AND (jobs.dependency_check_succeeded IS TRUE))
)
SELECT queue.id AS job_id,
queue.rank
CREATE INDEX jobs_buildroots_pkg_uuid ON jobs_buildroots USING btree (pkg_uuid);
+--
+-- Name: jobs_queue_ready; Type: INDEX; Schema: public; Owner: pakfire; Tablespace:
+--
+
+CREATE INDEX jobs_queue_ready ON jobs USING btree (id) WHERE ((state = 'new'::text) AND (dependency_check_succeeded IS TRUE));
+
+
--
-- Name: jobs_time_finished; Type: INDEX; Schema: public; Owner: pakfire; Tablespace:
--
color: yellow;
}
-table.builds tr.build td.jobs a.dependency_error {
- color: blue;
-}
-
table.builds tr.build td.jobs a.failed {
color: red;
}
<li><a class="build running" name="#">{{ _("Build is running") }}</a></li>
<li><a class="build failed" name="#">{{ _("Build has failed") }}</a></li>
<li><a class="build pending" name="#">{{ _("Build is waiting to be processed") }}</a></li>
- <li><a class="build dependency_error" name="#">{{ _("There was a dependency error when the package was built") }}</a></li>
<li><a class="build waiting" name="#">{{ _("Build is waiting for source to go to pending state") }}</a></li>
<li><a class="build dispatching" name="#">{{ _("Files of this build are transferred to the build server") }}</a></li>
<li><a class="build uploading" name="#">{{ _("Files are being uploaded to the service") }}</a></li>
<a href="/job/{{ job.uuid }}">{{ job.arch }}</a>
</td>
<td>
- {% if job.state == "new" %}
- {{ _("New") }}
- {% elif job.state == "pending" %}
+ {% if job.state == "pending" %}
{{ _("Pending") }}
{% elif job.state == "failed" %}
{{ _("Failed") }}
{{ _("Running") }}
{% elif job.state == "aborted" %}
{{ _("Aborted") }}
- {% elif job.state == "dependency_error" %}
- {{ _("Dependency error") }}
{% else %}
{{ job.state }}
{% end %}
<tr class="success">
{% elif job.state in ("dispatching", "uploading") %}
<tr class="info">
- {% elif job.state in ("aborted", "dependency_error", "failed") %}
+ {% elif job.state in ("aborted", "failed") %}
<tr class="error">
{% else %}
<tr>
classes.append("muted")
icon = "icon-warning-sign"
- elif state == "dependency_error":
- text = _("Dependency problem")
- classes.append("text-warning")
- icon = "icon-random"
-
elif state == "dispatching":
text = _("Dispatching")
classes.append("text-info")
classes.append("text-success")
icon = "icon-ok"
- elif state == "new":
- text = _("New")
- classes.append("muted")
- icon = "icon-asterisk"
-
elif state == "pending":
text = _("Pending")
classes.append("muted")