Skip to content
Permalink
Browse files

moving pipeline state to a separate table which for now contains lock… (

#3204)

* moving pipeline state to a separate table which for now contains locked information about the pipeline. This table could hold other state information for a given pipeline-config

* This commit also handles migration of locked column from pipelines table to pipelinestates

* Read locks needs to be held only if we are loading the state from db. Reading from cache could happen in parallel
  • Loading branch information...
jyotisingh authored and maheshp committed Apr 17, 2017
1 parent 9275d12 commit 11f19dbcb1006223b27afc34c749f85c5344f244
Showing with 1,061 additions and 508 deletions.
  1. +1 −0 .gitignore
  2. +94 −0 domain/src/com/thoughtworks/go/domain/PipelineState.java
  3. +9 −0 domain/src/com/thoughtworks/go/domain/StageIdentifier.java
  4. +68 −0 domain/test/com/thoughtworks/go/domain/PipelineStateTest.java
  5. +41 −0 server/db/migrate/h2deltas/1704003_pipeline_state_table.sql
  6. +0 −16 server/resources/com/thoughtworks/go/server/dao/maps/Pipeline.xml
  7. +2 −2 server/resources/com/thoughtworks/go/server/dao/maps/Stage.xml
  8. +31 −0 server/resources/hibernate-mappings/PipelineState.hbm.xml
  9. +35 −116 server/src/com/thoughtworks/go/server/dao/PipelineSqlMapDao.java
  10. +179 −0 server/src/com/thoughtworks/go/server/dao/PipelineStateDao.java
  11. +1 −1 server/src/com/thoughtworks/go/server/service/PipelineHistoryService.java
  12. +17 −11 server/src/com/thoughtworks/go/server/service/PipelineLockService.java
  13. +2 −5 server/src/com/thoughtworks/go/server/service/PipelineUnlockApiService.java
  14. +1 −0 server/test/common/com/thoughtworks/go/server/dao/DatabaseAccessHelper.java
  15. +17 −141 server/test/integration/com/thoughtworks/go/server/dao/PipelineSqlMapDaoIntegrationTest.java
  16. +216 −0 server/test/integration/com/thoughtworks/go/server/dao/PipelineStateDaoIntegrationTest.java
  17. +82 −171 server/test/{integration → unit}/com/thoughtworks/go/server/dao/PipelineSqlMapDaoCachingTest.java
  18. +41 −5 server/test/unit/com/thoughtworks/go/server/dao/PipelineSqlMapDaoTest.java
  19. +171 −0 server/test/unit/com/thoughtworks/go/server/dao/PipelineStateDaoCachingTest.java
  20. +2 −2 server/test/unit/com/thoughtworks/go/server/service/PipelineHistoryServiceTest.java
  21. +31 −25 server/test/unit/com/thoughtworks/go/server/service/PipelineLockServiceTest.java
  22. +15 −13 server/test/unit/com/thoughtworks/go/server/service/PipelineUnlockApiServiceTest.java
  23. +5 −0 server/test/unit/com/thoughtworks/go/server/service/StubGoCache.java
@@ -151,3 +151,4 @@ build/
out/
config/config-server/warnings.log
server/dev
**/.DS_Store
@@ -0,0 +1,94 @@
/*
* Copyright 2017 ThoughtWorks, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.thoughtworks.go.domain;

public class PipelineState extends PersistentObject {
private String pipelineName;
private boolean locked = false;
private long lockedByPipelineId;

private transient StageIdentifier lockedBy = null;
public final static PipelineState NOT_LOCKED = new PipelineState("NOT_LOCKED", -100);

public PipelineState() {
}

private PipelineState(String pipelineName, int id) {
this(pipelineName);
this.id = id;
}

public PipelineState(String pipelineName) {
this.pipelineName = pipelineName;
}

public PipelineState(String pipelineName, StageIdentifier identifier) {
this(pipelineName);
this.lockedBy = identifier;
}

public StageIdentifier getLockedBy() {
return lockedBy;
}

public void setLockedBy(StageIdentifier lockedBy) {
this.lockedBy = lockedBy;
}

public boolean isLocked() {
return locked;
}

public void lock(long lockedByPipelineId) {
this.lockedByPipelineId = lockedByPipelineId;
locked = true;
}

public void unlock() {
locked = false;
lockedBy = null;
lockedByPipelineId = 0;
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
if (!super.equals(o)) return false;

PipelineState that = (PipelineState) o;

if (locked != that.locked) return false;
if (lockedByPipelineId != that.lockedByPipelineId) return false;
if (!pipelineName.equals(that.pipelineName)) return false;
return lockedBy != null ? lockedBy.equals(that.lockedBy) : that.lockedBy == null;
}

@Override
public int hashCode() {
int result = super.hashCode();
result = 31 * result + pipelineName.hashCode();
result = 31 * result + (locked ? 1 : 0);
result = 31 * result + (int) (lockedByPipelineId ^ (lockedByPipelineId >>> 32));
result = 31 * result + (lockedBy != null ? lockedBy.hashCode() : 0);
return result;
}

public long getLockedByPipelineId() {
return lockedByPipelineId;
}
}
@@ -37,6 +37,15 @@ public StageIdentifier(Pipeline pipeline, Stage stage) {
this(pipeline.getName(), pipeline.getCounter(), pipeline.getLabel(), stage.getName(), String.valueOf(stage.getCounter()));
}

public StageIdentifier(String pipelineName, Integer pipelineCounter, String pipelineLabel, Long stageId, String stageName, String stageCounter) {
this.pipelineName = pipelineName;
this.pipelineCounter = pipelineCounter;
this.pipelineLabel = pipelineLabel;
id = stageId;
this.stageName = stageName;
this.stageCounter = stageCounter;
}

public StageIdentifier(String pipelineName, Integer pipelineCounter, String pipelineLabel, String stageName, String stageCounter) {
String label = StringUtils.isBlank(pipelineLabel) ? "latest" : pipelineLabel;
setLocatorAttributes(pipelineName, pipelineCounter, label, stageName, stageCounter);
@@ -0,0 +1,68 @@
/*
* Copyright 2017 ThoughtWorks, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package com.thoughtworks.go.domain;

import org.junit.Test;

import static org.hamcrest.core.Is.is;
import static org.junit.Assert.*;

public class PipelineStateTest {
@Test
public void shouldBeEqualToAnotherPipelineStateIfAllAttributesMatch() {
PipelineState pipelineState1 = new PipelineState("p", new StageIdentifier("p", 1, "1", 1L, "s", "1"));
PipelineState pipelineState2 = new PipelineState("p", new StageIdentifier("p", 1, "1", 1L, "s", "1"));
pipelineState1.lock(1);
pipelineState2.lock(1);
assertEquals(pipelineState1, pipelineState2);
}

@Test
public void shouldBeEqualToAnotherPipelineStateIfBothDoNotHaveLockedBy() {
PipelineState pipelineState1 = new PipelineState("p");
PipelineState pipelineState2 = new PipelineState("p");
pipelineState1.lock(1);
pipelineState2.lock(1);
assertEquals(pipelineState1, pipelineState2);
}

@Test
public void shouldNotBeEqualToAnotherPipelineStateIfAllAttributesDoNotMatch() {
PipelineState pipelineState1 = new PipelineState("p", new StageIdentifier("p", 1, "1", 1L, "s", "1"));
PipelineState pipelineState2 = new PipelineState("p", new StageIdentifier("p", 1, "1", 1L, "s", "1"));
pipelineState1.lock(1);
assertNotEquals(pipelineState1, pipelineState2);
}

@Test
public void shouldSetLockedByPipelineIdWhileLockingAPipeline() {
PipelineState pipelineState = new PipelineState("p");
pipelineState.lock(100);
assertThat(pipelineState.isLocked(), is(true));
assertThat(pipelineState.getLockedByPipelineId(), is(100L));
}

@Test
public void shouldUnsetLockedByPipelineIdWhileUnlockingAPipeline() {
PipelineState pipelineState = new PipelineState("p");
pipelineState.lock(100);

pipelineState.unlock();
assertThat(pipelineState.isLocked(), is(false));
assertThat(pipelineState.getLockedByPipelineId(), is(0L));
}
}
@@ -0,0 +1,41 @@
--
-- Copyright 2017 ThoughtWorks, Inc.
--
-- Licensed under the Apache License, Version 2.0 (the "License");
-- you may not use this file except in compliance with the License.
-- You may obtain a copy of the License at
--
-- http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing, software
-- distributed under the License is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-- See the License for the specific language governing permissions and
-- limitations under the License.
--

CREATE TABLE PipelineStates (
id BIGINT GENERATED BY DEFAULT AS IDENTITY (START WITH 1) PRIMARY KEY,
pipelineName VARCHAR_IGNORECASE(255) NOT NULL,
locked BOOLEAN,
lockedByPipelineId BIGINT,
);

ALTER TABLE PipelineStates ADD CONSTRAINT unique_pipeline_state UNIQUE (pipelineName);

INSERT INTO PipelineStates (pipelineName, locked, lockedByPipelineId) (select name, locked, id from pipelines where id in (select max(id) from pipelines where locked = true group by name));

DROP VIEW _stages;

CREATE VIEW _stages AS
SELECT s.*,
p.name pipelineName, p.buildCauseType, p.buildCauseBy, p.label pipelineLabel, p.buildCauseMessage, p.counter pipelineCounter, ps.locked, p.naturalOrder
FROM stages s
INNER JOIN pipelines p ON p.id = s.pipelineId
LEFT OUTER JOIN PipelineStates ps on ps.lockedByPipelineId = s.pipelineId;


ALTER TABLE pipelines drop column locked;

--//@UNDO

@@ -106,28 +106,12 @@
WHERE pipelineName = #pipelineName#
</update>

<update id="lockPipeline">
UPDATE pipelines
SET locked = true
WHERE id = #value#
</update>

<update id="unlockLockedPipeline" parameterClass="string">
UPDATE pipelines
SET locked = false
WHERE name = #value# and locked = true
</update>

<update id="updatePipelineComment">
UPDATE pipelines
SET comment = #comment#
WHERE name = #pipelineName# and counter = #pipelineCounter#
</update>

<select id="allLockedPipelines" resultClass="String">
SELECT name FROM pipelines WHERE locked = true
</select>

<select id="getPipelineHistoryCount" resultClass="java.lang.Integer">
SELECT COUNT(1) FROM pipelines WHERE name = #value#
</select>
@@ -743,11 +743,11 @@
ORDER BY builds.name, buildstatetransitions.id
</select>

<select id="lockedPipeline" resultMap="Stage.stageIdentifier" parameterClass="string">
<select id="lockedPipeline" resultMap="Stage.stageIdentifier">
SELECT pipelineName, pipelineCounter, pipelineLabel, id as stageId, name as stageName, counter as stageCounter
FROM _stages
WHERE locked = true
AND LOWER(pipelineName) = LOWER(#value#)
AND pipelineId = #pipelineId#
AND latestRun = true
ORDER BY id DESC
LIMIT 1
@@ -0,0 +1,31 @@
<?xml version="1.0"?>
<!--
~ Copyright 2017 ThoughtWorks, Inc.
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->

<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="com.thoughtworks.go.domain" default-access="field" default-lazy="false">
<class name="com.thoughtworks.go.domain.PipelineState" table="pipelinestates">
<id name="id" column="id">
<generator class="identity"/>
</id>
<property name="pipelineName"/>
<property name="locked"/>
<property name="lockedByPipelineId"/>
</class>
</hibernate-mapping>

0 comments on commit 11f19db

Please sign in to comment.
You can’t perform that action at this time.