Example #1
0
func (e *etcd) SaveRoute(route models.Route) error {
	key := generateHttpRouteKey(route)

	retries := 0

	for retries <= maxRetries {
		response, err := e.keysAPI.Get(context.Background(), key, readOpts())

		// Update
		if response != nil && err == nil {
			var existingRoute models.Route
			err = json.Unmarshal([]byte(response.Node.Value), &existingRoute)
			if err != nil {
				return err
			}

			route.ModificationTag = existingRoute.ModificationTag
			route.ModificationTag.Increment()

			routeJSON, _ := json.Marshal(route)
			_, err = e.keysAPI.Set(context.Background(), key, string(routeJSON), updateOptsWithTTL(route.TTL, response.Node.ModifiedIndex))
			if err == nil {
				break
			}
		} else if cerr, ok := err.(client.Error); ok && cerr.Code == client.ErrorCodeKeyNotFound { //create
			// Delete came in between a read and an update
			if retries > 0 {
				return ErrorConflict
			}

			var tag models.ModificationTag
			tag, err = models.NewModificationTag()
			if err != nil {
				return err
			}
			route.ModificationTag = tag
			routeJSON, _ := json.Marshal(route)
			_, err = e.keysAPI.Set(ctx(), key, string(routeJSON), createOpts(route.TTL))
			if err == nil {
				break
			}
		}

		// only retry on a compare and swap error
		if cerr, ok := err.(client.Error); ok && cerr.Code == client.ErrorCodeTestFailed {
			retries++
		} else {
			return err
		}
	}

	if retries > maxRetries {
		return ErrorConflict
	}
	return nil
}
Example #2
0
						fakeKeysAPI.GetReturns(nil, keyNotFoundError)
					})

					It("Creates a route if none exist", func() {
						err := fakeEtcd.SaveRoute(route)
						Expect(err).NotTo(HaveOccurred())
						Expect(fakeKeysAPI.GetCallCount()).To(Equal(1))
						Expect(fakeKeysAPI.SetCallCount()).To(Equal(1))
						_, _, json, _ := fakeKeysAPI.SetArgsForCall(0)
						Expect(json).To(ContainSubstring("\"index\":0"))
					})
				})

				Context("when an entry already exists", func() {
					BeforeEach(func() {
						route.ModificationTag = models.ModificationTag{Guid: "guid", Index: 5}
						routeJson, err := json.Marshal(&route)
						Expect(err).ToNot(HaveOccurred())
						fakeResp := &client.Response{Node: &client.Node{Value: string(routeJson)}}
						fakeKeysAPI.GetReturns(fakeResp, nil)
					})

					It("Updates the route and increments the tag index", func() {
						route2 := models.Route{
							Route:           "some-route/path",
							Port:            5500,
							IP:              "3.1.5.7",
							TTL:             1000,
							LogGuid:         "your-guid",
							RouteServiceUrl: "https://new-rs.com",
						}