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

Create a property service #132

Closed
allenxwang opened this issue Aug 15, 2013 · 4 comments
Closed

Create a property service #132

allenxwang opened this issue Aug 15, 2013 · 4 comments

Comments

@allenxwang
Copy link

Goals

The purpose of having a service for properties are the following

Enable the dynamic nature of the properties

Once we have a standard service for properties, we can create a standard PolledConfigurationSource on the client side to get all the properties, which can be changed dynamically on the server.

Hide persistence details and rely on API

So that you can switch persistence store without affecting clients

Provide property management functionalities

We are aiming to support these functionalities initially

  • Pluggable persistence, with implementation on Cassandra using Astyanax
  • Life cycle management
  • Validation
  • Query

A set of REST APIs as well as some UI will be provided.

Support scopes and property filtering based on scopes

With the service, you can create properties with the same name but different scopes. A client can query the service to get the properties for certain scopes. For example, there can be properties with the same name, but different values for different applications. One application can query the service to get the property for that specific application.

Architecture

The service will be a web application that manages the properties as resources. It is a Jersey based RESTful service. Configuration and wiring of implementation specific objects will be done via dependency injection with Guice.

Property Model

The following is the proposed Java model for Property

public class Property {
     // an ID associated with persistence store
     private String propertyId;
     // property name observed from client side
     private String key; 
     private String value;
     // validation rule, can be null if none or not supported
     private String constraints;
     private String description;
     private long lastUpdated;

     // attribute name/value pair like region=us-east-1
     // affect selection or filtering of properties.
     private Map<String, String> scopes;

     // attributes that are related to the server side 
     // operation of the property which do not have any effect
     // usage on the client side
     private Map<String, String> operationalAttributes;

     // setters and getters ...    
}

The following interfaces defines some meta data and operational attributes which are implementation specific:

public interface PropertyMetaData {
    /**
     * Return list of supported scopes for the property,
     * for example, "region", "env", "serverId"
     */ 
    public List<String> getSupportedScopes();

    /**
     * List of supported operational attributes,
     * for example, "lastUpdatedBy"
     */
    public List<String> getSupportedOperationalAttributes();
}

Data Access

The following is the interface for data access for the persistence store.

public interface PropertiesDAO {
    public List<Property> getAllProperties() throws Exception;

    public Property getProperty(String id) throws Exception;

    /**
     * @param skipPropWithNonexistCriteria whether we should skip a property if a specified scope 
     *          in the query does not apply to the property
     */
    public List<Property> queryProperties(Map<String, Collection<String>> scopes, boolean skipPropWithNonexistCriteria);

    public void createOrUpdateProperty(Property property, Map<String, Object> operationalAttributes) throws Exception;

    public void deleteProperty(String id, Map<String, Object> operationalAttributes) throws Exception;

    public void init() throws Exception;

    public void shutDown() throws Exception;

    public void updateJournal(Property property, Constants.Action action, 
            Map<String, Object> operationalAttributes) throws Exception;

    public boolean propertiesChangedSince(long timeStamp);

    // get the time stamp any property is last updated in the persistence store
    public long getLastModified();
}

Some implementation loads all properties from persistence into memory. Additional functionalities are required for such implementation like refresh and keeping a certain level of data consistency. These functionalities will be defined in additional class/interface.

REST API

The REST API should support creation, retrieval, query/search, update and deletion of property.

The response code follows this convention:

200 - request is successful
400 - malformed request
404 - requested property does not exist (in retrieval, update and deletion)
405 - trying to update a field of property that is supposed to immutable
409 - In creation, property with the same key and scopes already exist
500 - unexpected server side exception occurred

Creation

POST <path>/property

Body of the POST request will be the serialized version of Property.

Response payload is the serialized version of the final property created, including property ID.

Example of request payload:

{"key": "foo", "value": "bar", 
 "description": "this property is used to determine behavior of foo",
 "scopes": {"region":"us-east-1", "env":"prod"}, 
 "operationalAttributes":{"lastUpdatedBy": "allen", "source":"asgard", "ticket": "JIRA12345"},
}

Example of response payload:

{"propertyId": "1234567",
 "key": "foo", "value": "bar", 
 "description": "this property is used to determine behavior of foo",
 "scopes": {"region":"us-east-1", "env":"prod"}, 
 "operationalAttributes":{"lastUpdatedBy": "allen", "source":"asgard", "ticket": "JIRA12345"},
 "lastUpdated":"2013-02-04T23:34:02.968Z"
}

Update

Once a property is created, only the following fields allow update:

  • value
  • constraint
  • description
  • operational attributes

Scopes should not be updated. Instead, new property should be created with the desired new scope and the old property can be deleted if the scopes are no longer applicable.

The HTTP Verb for update should ideally be "PATCH". However, since it just gets standardized and there is limited support, we are going to use "POST" instead.

POST <path>/property?propertyId=<id>

An example of UPDATE payload:

{ "value": "fooAndBar", 
 "description": "this property is used to determine behavior of foo and bar",
 "operationalAttributes":{"lastUpdatedBy": "allen", "source":"asgard", "ticket": "JIRA1234567"}
}

An example of UPDATE response:

{"propertyId": "1234567",
 "key": "foo", "value": "fooAndBar", 
 "description": "this property is used to determine behavior of foo and bar",
 "scopes": {"region":"us-east-1", "env":"prod"}, 
 "operationalAttributes":{"lastUpdatedBy": "allen", "source":"asgard", "ticket": "JIRA234567"},
 "lastUpdated":"2013-03-05T20:12:02.000Z"
}

Retrieval of a single property

GET <path>/property?id=<id>

Instead of put the property ID as part of path, it is added as a query parameter. The reason is that the ID may contain path character, for example "/", which will confuse the service. On the other hand, using URL encoded query parameter has better interoperability.

The payload of response will include the property.

Query of properties

This REST API is used to return a list of properties that matches scopes specified in the request.

GET <path>/query?<scopes with acceptable values>

For example

GET /REST/query?region=us-east-1&region=us-west-2&env=prod&appId=movieservice&appId=

The query looks for properties that matches the following criteria:

  • application is "movieservice" or nonexistent
  • region is either us-east-1 or us-west-2
  • environment is prod

Here is an example of response payload:

[
{"propertyId": "1234567",
 "key": "foo", "value": "fooAndBar", 
 "description": "this property is used to determine behavior of foo and bar",
 "scopes": {"region":"us-east-1", "env":"prod"}, 
 "operationalAttributes":{"lastUpdatedBy": "allen", "source":"asgard", "ticket": "JIRA234567"},
 "lastUpdated":"2013-03-05T20:12:02.000Z"
},
// other properties
]

Deletion

DELETE <path>/property?id=<id>&<operational attributes>

There is no response payload. The response code indicates the result.

@floer32
Copy link

floer32 commented Jun 2, 2015

+1

2 similar comments
@martijnburger
Copy link

+1

@newdha
Copy link

newdha commented Nov 28, 2016

+1

@rgallardo-netflix
Copy link
Contributor

The team has no bandwidth to try to implement this.

@rgallardo-netflix rgallardo-netflix closed this as not planned Won't fix, can't repro, duplicate, stale Jul 7, 2023
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

No branches or pull requests

5 participants