abstract some shared logic