# -*- coding: utf-8 -*- # Copyright 2010 - 2017 RhodeCode GmbH and the AppEnlight project authors # # 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. import sqlalchemy as sa from appenlight.lib.ext_json import json from pyramid.threadlocal import get_current_registry from appenlight.models.tag import Tag from appenlight.models.services.base import BaseService from appenlight.models import get_db_session class TagService(BaseService): @classmethod def cut_name(cls, tag_name): return tag_name[:32] @classmethod def cut_value(cls, value): if isinstance(value, str): value = value[:128] return value @classmethod def by_resource_id_and_value(cls, resource_id, tag_name, value, db_session=None, create_missing=True): """ Fetches tag and creates a new one if missing """ db_session = get_db_session(db_session) registry = get_current_registry() @registry.cache_regions.redis_min_10.cache_on_arguments( namespace='TagService.by_resource_id_and_value') def cached(resource_id, tag_name, value): reduced_name = cls.cut_name(tag_name.decode('utf8')) reduced_value = cls.cut_value(value.decode('utf8')) query = db_session.query(Tag) query = query.filter(Tag.resource_id == resource_id) query = query.filter(Tag.name == reduced_name) query = query.filter(sa.cast(Tag.value, sa.types.TEXT) == sa.cast(json.dumps(reduced_value), sa.types.TEXT)) tag = query.first() if tag: db_session.expunge(tag) return tag view = cached(resource_id, tag_name.encode('utf8'), value.encode('utf8')) if not view and create_missing: view = cls.create_tag(resource_id, cls.cut_name(tag_name), cls.cut_value(value), db_session) cached.invalidate(resource_id, tag_name.encode('utf8'), value.encode('utf8')) return view @classmethod def create_tag(cls, resource_id, tag_name, value, db_session=None): tag = Tag(resource_id=resource_id, name=cls.cut_name(tag_name), value=cls.cut_value(value)) db_session = get_db_session(db_session) db_session.add(tag) db_session.flush() return tag @classmethod def by_tag_id(cls, tag_id, db_session=None): db_session = get_db_session(db_session) registry = get_current_registry() @registry.cache_regions.redis_min_10.cache_on_arguments( namespace='TagService.by_tag_id') def cached(tag_id): tag = db_session.query(Tag).filter(Tag.id == tag_id).first() if tag: db_session.expunge(tag) return tag return cached(tag_id)