function should be idempotent