require 'p4_project_services_data' module P4ProjectServices # Defines data access using our underlying P4 Web API file methods. # class ProjectDao # The P4WebAPIClient to use for all requests attr_accessor :client def initialize(client) @client = client end # Returns all projects in the system. # # This will hit *all* project metadata in the system. Use sparingly. # # `client` is a P4WebAPIClient. def find_all db_projects = Models::Project.dataset.all db_projects.map { |x| to_data_project(x) } end # Returns an array of projects meeting various filter criteria # # If no filter criteria are used, will basically call find_all_projects. # # `client` is a P4WebAPIClient. def find(names: nil, owners: nil, extensions: nil) return find_all unless names or owners or extensions ds = Models::Project.dataset.select_all(:projects) ds = ds.where('name in ?', names) if names.is_a?(Array) ds = ds.where('name = ?', names) if names.is_a?(String) ds = ds.where('owner in ?', owners) if owners.is_a?(Array) ds = ds.where('owner = ?', owners) if owners.is_a?(String) if extensions.is_a?(Array) ds = ds.where('iid in ' + '(select project_iid from extensions where content_type in ?)', extensions) elsif extensions.is_a?(String) ds = ds.where('iid in ' + '(select project_iid from extensions where content_type = ?)', extensions) end ds.all.map { |x| to_data_project(x) } end def find_by_id(id) db_project = Models::Project.dataset.where('id = ?', id).first to_data_project(db_project) end def create(project) unless project.id project.id = project.name.gsub(/[^a-zA-Z0-9_]/, '_').downcase end depotPath = "//.project/#{project.id}/project.json" json = JSON.generate(project) files_to_update = [{ depot_file: depotPath, content: json, action: 'upload', required_revision: 0 }] client.create_change({files: files_to_update}) project_file = client.file(depotPath) db_project = Models::Project.new db_project.id = project.id db_project.name = project.name db_project.version = project_file.revision db_project.description = project.description if project.description db_project.owner = project.owner if project.owner db_project.group = project.group if project.group db_project.save if project.branches project.branches.each do |branch| db_branch = Models::Branch.new db_branch.id = branch.id db_branch.name = branch.name db_branch.stream = branch.stream if branch.stream db_project.add_branch(db_branch) db_project.save if branch.view branch.view.each do |v| db_view = Models::View.new db_view.depot_path = v.depot_path db_view.view_path = v.view_path db_branch.add_view(db_view) db_branch.save end end end end unless project.extension_keys.empty? project.extension_keys.each do |key| db_ext = Models::Extension.new db_ext.content_type = project.extensions[key].class.content_type db_ext.json = project.extensions[key].to_json db_project.add_extension(db_ext) db_project.save end end end def save(project) depotPath = "//.project/#{project.id}/project.json" json = JSON.generate(project) project_file = client.file(depotPath) db_project = Models::Project.dataset.where(id: project.id).first raise "cached project doesn't exist #{project.id}" if db_project.nil? files_to_update = [{ depot_file: depotPath, content: json, action: 'upload', required_revision: project_file.revision }] client.create_change({files: files_to_update}) # Need the update file data since we can't really predict the revision project_file = client.file(depotPath) # Update DB project db_project.name = project.name if project.name db_project.version = project_file.revision db_project.description = project.description if project.description db_project.owner = project.owner if project.owner db_project.group = project.group if project.group if project.branches project.branches.each do |branch| db_branch = Models::Branch.dataset.where(project_iid: db_project.iid, id: branch.id) .first add = false if db_branch.nil? db_branch = Models::Branch.new if db_branch.nil? add = true end db_branch.id = branch.id db_branch.name = branch.name if branch.name db_branch.sream = branch.stream if branch.stream db_project.add_branch(db_branch) if add db_branch.save if add if branch.view db_branch.remove_all_views branch.view.each do |v| db_view = Models::View.new db_view.depot_path = v.depot_path db_view.view_path = v.view_path db_branch.add_view(db_view) db_branch.save end end end end unless project.extension_keys.empty? db_project.remove_all_extensions project.extension_keys.each do |key| db_ext = Models::Extension.new db_ext.content_type = project.extensions[key].class.content_type db_ext.json = project.extensions[key].to_json db_project.add_extension(db_ext) end end db_project.save end def load_project_by_depot_path(depot_path) f = client.file(depot_path) h = JSON.parse(f.content) P4ProjectServicesData::Project.json_create(h) end private # Convert P4ProjectServices::Model::Project to P4ProjectServicesData::Project def to_data_project(db) data_project = P4ProjectServicesData::Project.new data_project.id = db.id data_project.name = db.name data_project.version = db.version data_project.description = db.description if db.description data_project.owner = db.owner if db.owner data_project.group = db.group if db.group if db.branches data_project.branches = db.branches.map do |b| branch = P4ProjectServicesData::Branch.new branch.id = b.id branch.name = b.name branch.stream = b.stream if b.stream if b.views branch.view = b.views.map do |v| view = P4ProjectServicesData::View.new view.depot_path = v.depot_path view.view_path = v.view_path view end end branch end end if db.extensions db.extensions.each do |ex| if ex.content_type == P4ProjectServicesData::Extensions::Phoenix.content_type phoenix = P4ProjectServicesData::Extensions::Phoenix.json_create(JSON.parse(ex.json)) data_project.extensions = {} unless data_project.extensions data_project.extensions[P4ProjectServicesData::Extensions::Phoenix.content_type] = phoenix end end end data_project end end end
# | Change | User | Description | Committed | |
---|---|---|---|---|---|
#8 | 13972 | tjuricek |
Removing old microservice implementations. The system is now mostly a monolith. Eventually there will be a websocket service. |
||
#7 | 13839 | tjuricek |
Conversion of the p4_project_service microservice to new monolithic system. This may not have an HTTP front end in the monolithic system. Project services are really just about how the core object model is structured. It's likely that each application will add their own wrinkles and extensions to the system, so it's unlikely we'll need a generic "project model". Exactly how extensions are registered and used is still a bit TBD at the moment. Previously they were to be registered webhooks, that model may change. Does not include tests yet. |
||
#6 | 13481 | tjuricek |
Tests for the p4 web api and p4 project services now pass against a development setup both in and out of the docker cluster. Note that configuration *has not* been finalized, so conventions to dealing with development vs production need to be organized a bit. |
||
#5 | 13474 | tjuricek | Corrected regressions that broke the API and Project services specs. | ||
#4 | 13465 | tjuricek | Fix query for extensions. | ||
#3 | 13463 | tjuricek | Replace crappy indexing mechanism with Postgres queries. | ||
#2 | 13459 | tjuricek |
Return the created project when creating a new project, since default values will often be filled out. Allow new projects to be created only with names set. We'll generate an ID at the moment, when I have better indexing, I'll double check for uniqueness. |
||
#1 | 13412 | tjuricek |
Initial version of the web-services mainline. This is a collection of several projects, that will likely often get released together, though many of them may not always be relevant. See the README for more information. |